mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into android_goto_splash
This commit is contained in:
commit
78c50410b3
35 changed files with 787 additions and 107 deletions
|
@ -470,7 +470,6 @@ void EntityServer::startDynamicDomainVerification() {
|
||||||
// Delete the entity if it doesn't pass static certificate verification
|
// Delete the entity if it doesn't pass static certificate verification
|
||||||
tree->deleteEntity(i.value(), true);
|
tree->deleteEntity(i.value(), true);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
QNetworkRequest networkRequest;
|
QNetworkRequest networkRequest;
|
||||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
@ -490,9 +489,13 @@ void EntityServer::startDynamicDomainVerification() {
|
||||||
|
|
||||||
if (networkReply->error() == QNetworkReply::NoError) {
|
if (networkReply->error() == QNetworkReply::NoError) {
|
||||||
if (jsonObject["domain_id"].toString() != thisDomainID) {
|
if (jsonObject["domain_id"].toString() != thisDomainID) {
|
||||||
qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
|
if (entity->getAge() > (_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS/MSECS_PER_SECOND)) {
|
||||||
<< "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << i.value();
|
qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
|
||||||
tree->deleteEntity(i.value(), true);
|
<< "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << i.value();
|
||||||
|
tree->deleteEntity(i.value(), true);
|
||||||
|
} else {
|
||||||
|
qCDebug(entities) << "Entity failed dynamic domain verification, but was created too recently to necessitate deletion:" << i.value();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qCDebug(entities) << "Entity passed dynamic domain verification:" << i.value();
|
qCDebug(entities) << "Entity passed dynamic domain verification:" << i.value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ Rectangle {
|
||||||
root.activeView = "checkoutFailure";
|
root.activeView = "checkoutFailure";
|
||||||
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
|
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
|
||||||
} else {
|
} else {
|
||||||
|
root.certificateId = result.data.certificate_id;
|
||||||
root.itemHref = result.data.download_url;
|
root.itemHref = result.data.download_url;
|
||||||
if (result.data.categories.indexOf("Wearables") > -1) {
|
if (result.data.categories.indexOf("Wearables") > -1) {
|
||||||
root.itemType = "wearable";
|
root.itemType = "wearable";
|
||||||
|
@ -188,7 +189,7 @@ Rectangle {
|
||||||
onItemHrefChanged: {
|
onItemHrefChanged: {
|
||||||
if (root.itemHref.indexOf(".fst") > -1) {
|
if (root.itemHref.indexOf(".fst") > -1) {
|
||||||
root.itemType = "avatar";
|
root.itemType = "avatar";
|
||||||
} else if (root.itemHref.indexOf('.json.gz') > -1) {
|
} else if (root.itemHref.indexOf('.json.gz') > -1 || root.itemHref.indexOf('.content.zip') > -1) {
|
||||||
root.itemType = "contentSet";
|
root.itemType = "contentSet";
|
||||||
} else if (root.itemHref.indexOf('.app.json') > -1) {
|
} else if (root.itemHref.indexOf('.app.json') > -1) {
|
||||||
root.itemType = "app";
|
root.itemType = "app";
|
||||||
|
@ -772,7 +773,7 @@ Rectangle {
|
||||||
lightboxPopup.button1text = "CANCEL";
|
lightboxPopup.button1text = "CANCEL";
|
||||||
lightboxPopup.button1method = "root.visible = false;"
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
lightboxPopup.button2text = "CONFIRM";
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "');" +
|
lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "', '" + root.certificateId + "');" +
|
||||||
"root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" +
|
"root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" +
|
||||||
"UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');";
|
"UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');";
|
||||||
lightboxPopup.visible = true;
|
lightboxPopup.visible = true;
|
||||||
|
|
|
@ -564,7 +564,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Tablet.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
if (root.itemType === "contentSet") {
|
if (root.itemType === "contentSet") {
|
||||||
sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref});
|
sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref, certID: root.certificateId});
|
||||||
} else if (root.itemType === "avatar") {
|
} else if (root.itemType === "avatar") {
|
||||||
sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
|
sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
|
||||||
} else if (root.itemType === "app") {
|
} else if (root.itemType === "app") {
|
||||||
|
|
|
@ -486,7 +486,7 @@ Rectangle {
|
||||||
lightboxPopup.button1text = "CANCEL";
|
lightboxPopup.button1text = "CANCEL";
|
||||||
lightboxPopup.button1method = "root.visible = false;"
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
lightboxPopup.button2text = "CONFIRM";
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "'); root.visible = false;";
|
lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "', '" + msg.certID + "'); root.visible = false;";
|
||||||
lightboxPopup.visible = true;
|
lightboxPopup.visible = true;
|
||||||
} else if (msg.method === "showChangeAvatarLightbox") {
|
} else if (msg.method === "showChangeAvatarLightbox") {
|
||||||
lightboxPopup.titleText = "Change Avatar";
|
lightboxPopup.titleText = "Change Avatar";
|
||||||
|
@ -792,7 +792,7 @@ Rectangle {
|
||||||
currentItemType = "avatar";
|
currentItemType = "avatar";
|
||||||
} else if (currentCategories.indexOf("Wearables") > -1) {
|
} else if (currentCategories.indexOf("Wearables") > -1) {
|
||||||
currentItemType = "wearable";
|
currentItemType = "wearable";
|
||||||
} else if (currentRootFileUrl.endsWith('.json.gz')) {
|
} else if (currentRootFileUrl.endsWith('.json.gz') || currentRootFileUrl.endsWith('.content.zip')) {
|
||||||
currentItemType = "contentSet";
|
currentItemType = "contentSet";
|
||||||
} else if (currentRootFileUrl.endsWith('.app.json')) {
|
} else if (currentRootFileUrl.endsWith('.app.json')) {
|
||||||
currentItemType = "app";
|
currentItemType = "app";
|
||||||
|
|
|
@ -67,8 +67,8 @@ using namespace std;
|
||||||
|
|
||||||
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
|
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
|
||||||
|
|
||||||
const float YAW_SPEED_DEFAULT = 100.0f; // degrees/sec
|
const float YAW_SPEED_DEFAULT = 75.0f; // degrees/sec
|
||||||
const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec
|
const float PITCH_SPEED_DEFAULT = 50.0f; // degrees/sec
|
||||||
|
|
||||||
const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed
|
const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed
|
||||||
const float MIN_AVATAR_SPEED = 0.05f;
|
const float MIN_AVATAR_SPEED = 0.05f;
|
||||||
|
@ -2227,7 +2227,7 @@ void MyAvatar::updateActionMotor(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float boomChange = getDriveKey(ZOOM);
|
float boomChange = getDriveKey(ZOOM);
|
||||||
_boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange;
|
_boomLength += 4.0f * _boomLength * boomChange + boomChange * boomChange;
|
||||||
_boomLength = glm::clamp<float>(_boomLength, ZOOM_MIN, ZOOM_MAX);
|
_boomLength = glm::clamp<float>(_boomLength, ZOOM_MIN, ZOOM_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2760,6 +2760,18 @@ bool MyAvatar::isDriveKeyDisabled(DriveKeys key) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::triggerVerticalRecenter() {
|
||||||
|
_follow.setForceActivateVertical(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::triggerHorizontalRecenter() {
|
||||||
|
_follow.setForceActivateHorizontal(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::triggerRotationRecenter() {
|
||||||
|
_follow.setForceActivateRotation(true);
|
||||||
|
}
|
||||||
|
|
||||||
// old school meat hook style
|
// old school meat hook style
|
||||||
glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const {
|
glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const {
|
||||||
glm::vec3 headPosition;
|
glm::vec3 headPosition;
|
||||||
|
@ -2957,7 +2969,9 @@ void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) {
|
||||||
bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||||
const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees
|
const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees
|
||||||
glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix);
|
glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix);
|
||||||
|
|
||||||
return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD;
|
return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||||
|
@ -2974,6 +2988,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
||||||
const float MAX_FORWARD_LEAN = 0.15f;
|
const float MAX_FORWARD_LEAN = 0.15f;
|
||||||
const float MAX_BACKWARD_LEAN = 0.1f;
|
const float MAX_BACKWARD_LEAN = 0.1f;
|
||||||
|
|
||||||
|
|
||||||
if (forwardLeanAmount > 0 && forwardLeanAmount > MAX_FORWARD_LEAN) {
|
if (forwardLeanAmount > 0 && forwardLeanAmount > MAX_FORWARD_LEAN) {
|
||||||
return true;
|
return true;
|
||||||
} else if (forwardLeanAmount < 0 && forwardLeanAmount < -MAX_BACKWARD_LEAN) {
|
} else if (forwardLeanAmount < 0 && forwardLeanAmount < -MAX_BACKWARD_LEAN) {
|
||||||
|
@ -2981,6 +2996,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar,
|
||||||
}
|
}
|
||||||
|
|
||||||
return fabs(lateralLeanAmount) > MAX_LATERAL_LEAN;
|
return fabs(lateralLeanAmount) > MAX_LATERAL_LEAN;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const {
|
||||||
|
@ -2988,6 +3004,7 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co
|
||||||
const float CYLINDER_BOTTOM = -1.5f;
|
const float CYLINDER_BOTTOM = -1.5f;
|
||||||
|
|
||||||
glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix);
|
glm::vec3 offset = extractTranslation(desiredBodyMatrix) - extractTranslation(currentBodyMatrix);
|
||||||
|
|
||||||
return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM);
|
return (offset.y > CYLINDER_TOP) || (offset.y < CYLINDER_BOTTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3005,6 +3022,19 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
||||||
if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
|
if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
|
||||||
activate(Vertical);
|
activate(Vertical);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!isActive(Rotation) && getForceActivateRotation()) {
|
||||||
|
activate(Rotation);
|
||||||
|
setForceActivateRotation(false);
|
||||||
|
}
|
||||||
|
if (!isActive(Horizontal) && getForceActivateHorizontal()) {
|
||||||
|
activate(Horizontal);
|
||||||
|
setForceActivateHorizontal(false);
|
||||||
|
}
|
||||||
|
if (!isActive(Vertical) && getForceActivateVertical()) {
|
||||||
|
activate(Vertical);
|
||||||
|
setForceActivateVertical(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * desiredBodyMatrix;
|
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * desiredBodyMatrix;
|
||||||
|
@ -3054,6 +3084,30 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::FollowHelper::getForceActivateRotation() const {
|
||||||
|
return _forceActivateRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::FollowHelper::setForceActivateRotation(bool val) {
|
||||||
|
_forceActivateRotation = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::FollowHelper::getForceActivateVertical() const {
|
||||||
|
return _forceActivateVertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::FollowHelper::setForceActivateVertical(bool val) {
|
||||||
|
_forceActivateVertical = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::FollowHelper::getForceActivateHorizontal() const {
|
||||||
|
return _forceActivateHorizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::FollowHelper::setForceActivateHorizontal(bool val) {
|
||||||
|
_forceActivateHorizontal = val;
|
||||||
|
}
|
||||||
|
|
||||||
float MyAvatar::getAccelerationEnergy() {
|
float MyAvatar::getAccelerationEnergy() {
|
||||||
glm::vec3 velocity = getWorldVelocity();
|
glm::vec3 velocity = getWorldVelocity();
|
||||||
int changeInVelocity = abs(velocity.length() - priorVelocity.length());
|
int changeInVelocity = abs(velocity.length() - priorVelocity.length());
|
||||||
|
|
|
@ -404,6 +404,32 @@ public:
|
||||||
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
Q_INVOKABLE void enableDriveKey(DriveKeys key);
|
||||||
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
*The triggerVerticalRecenter function activates one time the recentering
|
||||||
|
*behaviour in the vertical direction. This call is only takes effect when the property
|
||||||
|
*MyAvatar.hmdLeanRecenterEnabled is set to false.
|
||||||
|
*@function MyAvatar.triggerVerticalRecenter
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
*The triggerHorizontalRecenter function activates one time the recentering behaviour
|
||||||
|
*in the horizontal direction. This call is only takes effect when the property
|
||||||
|
*MyAvatar.hmdLeanRecenterEnabled is set to false.
|
||||||
|
*@function MyAvatar.triggerHorizontalRecenter
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
*The triggerRotationRecenter function activates one time the recentering behaviour
|
||||||
|
*in the rotation of the root of the avatar. This call is only takes effect when the property
|
||||||
|
*MyAvatar.hmdLeanRecenterEnabled is set to false.
|
||||||
|
*@function MyAvatar.triggerRotationRecenter
|
||||||
|
*/
|
||||||
|
|
||||||
|
Q_INVOKABLE void triggerVerticalRecenter();
|
||||||
|
Q_INVOKABLE void triggerHorizontalRecenter();
|
||||||
|
Q_INVOKABLE void triggerRotationRecenter();
|
||||||
|
|
||||||
eyeContactTarget getEyeContactTarget();
|
eyeContactTarget getEyeContactTarget();
|
||||||
|
|
||||||
const MyHead* getMyHead() const;
|
const MyHead* getMyHead() const;
|
||||||
|
@ -803,6 +829,15 @@ private:
|
||||||
bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
bool shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const;
|
||||||
void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput);
|
void prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& bodySensorMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput);
|
||||||
glm::mat4 postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
glm::mat4 postPhysicsUpdate(const MyAvatar& myAvatar, const glm::mat4& currentBodyMatrix);
|
||||||
|
bool getForceActivateRotation() const;
|
||||||
|
void setForceActivateRotation(bool val);
|
||||||
|
bool getForceActivateVertical() const;
|
||||||
|
void setForceActivateVertical(bool val);
|
||||||
|
bool getForceActivateHorizontal() const;
|
||||||
|
void setForceActivateHorizontal(bool val);
|
||||||
|
std::atomic<bool> _forceActivateRotation{ false };
|
||||||
|
std::atomic<bool> _forceActivateVertical{ false };
|
||||||
|
std::atomic<bool> _forceActivateHorizontal{ false };
|
||||||
};
|
};
|
||||||
FollowHelper _follow;
|
FollowHelper _follow;
|
||||||
|
|
||||||
|
@ -839,6 +874,7 @@ private:
|
||||||
|
|
||||||
bool _hmdLeanRecenterEnabled { true };
|
bool _hmdLeanRecenterEnabled { true };
|
||||||
bool _sprint { false };
|
bool _sprint { false };
|
||||||
|
|
||||||
AnimPose _prePhysicsRoomPose;
|
AnimPose _prePhysicsRoomPose;
|
||||||
std::mutex _holdActionsMutex;
|
std::mutex _holdActionsMutex;
|
||||||
std::vector<AvatarActionHold*> _holdActions;
|
std::vector<AvatarActionHold*> _holdActions;
|
||||||
|
|
|
@ -293,7 +293,7 @@ void Ledger::account() {
|
||||||
// The api/failResponse is called just for the side effect of logging.
|
// The api/failResponse is called just for the side effect of logging.
|
||||||
void Ledger::updateLocationSuccess(QNetworkReply& reply) { apiResponse("updateLocation", reply); }
|
void Ledger::updateLocationSuccess(QNetworkReply& reply) { apiResponse("updateLocation", reply); }
|
||||||
void Ledger::updateLocationFailure(QNetworkReply& reply) { failResponse("updateLocation", reply); }
|
void Ledger::updateLocationFailure(QNetworkReply& reply) { failResponse("updateLocation", reply); }
|
||||||
void Ledger::updateLocation(const QString& asset_id, const QString location, const bool controlledFailure) {
|
void Ledger::updateLocation(const QString& asset_id, const QString& location, const bool& alsoUpdateSiblings, const bool controlledFailure) {
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
|
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
|
||||||
uint walletStatus = walletScriptingInterface->getWalletStatus();
|
uint walletStatus = walletScriptingInterface->getWalletStatus();
|
||||||
|
@ -308,6 +308,9 @@ void Ledger::updateLocation(const QString& asset_id, const QString location, con
|
||||||
QJsonObject transaction;
|
QJsonObject transaction;
|
||||||
transaction["certificate_id"] = asset_id;
|
transaction["certificate_id"] = asset_id;
|
||||||
transaction["place_name"] = location;
|
transaction["place_name"] = location;
|
||||||
|
if (alsoUpdateSiblings) {
|
||||||
|
transaction["also_update_siblings"] = true;
|
||||||
|
}
|
||||||
QJsonDocument transactionDoc{ transaction };
|
QJsonDocument transactionDoc{ transaction };
|
||||||
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
||||||
signedSend("transaction", transactionString, key, "location", "updateLocationSuccess", "updateLocationFailure", controlledFailure);
|
signedSend("transaction", transactionString, key, "location", "updateLocationSuccess", "updateLocationFailure", controlledFailure);
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
void inventory(const QStringList& keys);
|
void inventory(const QStringList& keys);
|
||||||
void history(const QStringList& keys, const int& pageNumber);
|
void history(const QStringList& keys, const int& pageNumber);
|
||||||
void account();
|
void account();
|
||||||
void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false);
|
void updateLocation(const QString& asset_id, const QString& location, const bool& alsoUpdateSiblings = false, const bool controlledFailure = false);
|
||||||
void certificateInfo(const QString& certificateId);
|
void certificateInfo(const QString& certificateId);
|
||||||
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
|
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||||
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
|
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
|
||||||
|
|
|
@ -190,7 +190,9 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou
|
||||||
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
|
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlCommerce::replaceContentSet(const QString& itemHref) {
|
void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) {
|
||||||
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
|
ledger->updateLocation(certificateID, DependencyManager::get<AddressManager>()->getPlaceName(), true);
|
||||||
qApp->replaceDomainContent(itemHref);
|
qApp->replaceDomainContent(itemHref);
|
||||||
QJsonObject messageProperties = {
|
QJsonObject messageProperties = {
|
||||||
{ "status", "SuccessfulRequestToReplaceContent" },
|
{ "status", "SuccessfulRequestToReplaceContent" },
|
||||||
|
|
|
@ -84,7 +84,7 @@ protected:
|
||||||
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
|
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||||
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
|
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
|
||||||
|
|
||||||
Q_INVOKABLE void replaceContentSet(const QString& itemHref);
|
Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID);
|
||||||
|
|
||||||
Q_INVOKABLE QString getInstalledApps();
|
Q_INVOKABLE QString getInstalledApps();
|
||||||
Q_INVOKABLE bool installApp(const QString& appHref);
|
Q_INVOKABLE bool installApp(const QString& appHref);
|
||||||
|
|
|
@ -80,7 +80,7 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
|
||||||
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path",
|
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path",
|
||||||
dropEvent ? dropHelpText : helpText, mapping);
|
dropEvent ? dropHelpText : helpText, mapping);
|
||||||
|
|
||||||
if (!result.isValid()) {
|
if (!result.isValid() || result.toString() == "") {
|
||||||
completedCallback.call({ -1 });
|
completedCallback.call({ -1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1246,6 +1246,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
|
||||||
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) {
|
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) {
|
||||||
|
|
||||||
|
const bool ENABLE_POLE_VECTORS = false;
|
||||||
const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f;
|
const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f;
|
||||||
|
|
||||||
int hipsIndex = indexOfJoint("Hips");
|
int hipsIndex = indexOfJoint("Hips");
|
||||||
|
@ -1268,7 +1269,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
int handJointIndex = _animSkeleton->nameToJointIndex("LeftHand");
|
int handJointIndex = _animSkeleton->nameToJointIndex("LeftHand");
|
||||||
int armJointIndex = _animSkeleton->nameToJointIndex("LeftArm");
|
int armJointIndex = _animSkeleton->nameToJointIndex("LeftArm");
|
||||||
int elbowJointIndex = _animSkeleton->nameToJointIndex("LeftForeArm");
|
int elbowJointIndex = _animSkeleton->nameToJointIndex("LeftForeArm");
|
||||||
if (!leftArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
|
if (ENABLE_POLE_VECTORS && !leftArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
|
||||||
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, true);
|
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, true);
|
||||||
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
||||||
|
@ -1315,7 +1316,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
|
||||||
int handJointIndex = _animSkeleton->nameToJointIndex("RightHand");
|
int handJointIndex = _animSkeleton->nameToJointIndex("RightHand");
|
||||||
int armJointIndex = _animSkeleton->nameToJointIndex("RightArm");
|
int armJointIndex = _animSkeleton->nameToJointIndex("RightArm");
|
||||||
int elbowJointIndex = _animSkeleton->nameToJointIndex("RightForeArm");
|
int elbowJointIndex = _animSkeleton->nameToJointIndex("RightForeArm");
|
||||||
if (!rightArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
|
if (ENABLE_POLE_VECTORS && !rightArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
|
||||||
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, false);
|
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, false);
|
||||||
|
|
||||||
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
// smooth toward desired pole vector from previous pole vector... to reduce jitter
|
||||||
|
@ -1555,18 +1556,21 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
||||||
updateFeet(leftFootEnabled, rightFootEnabled,
|
updateFeet(leftFootEnabled, rightFootEnabled,
|
||||||
params.primaryControllerPoses[PrimaryControllerType_LeftFoot], params.primaryControllerPoses[PrimaryControllerType_RightFoot]);
|
params.primaryControllerPoses[PrimaryControllerType_LeftFoot], params.primaryControllerPoses[PrimaryControllerType_RightFoot]);
|
||||||
|
|
||||||
|
|
||||||
|
if (headEnabled) {
|
||||||
|
// Blend IK chains toward the joint limit centers, this should stablize head and hand ik.
|
||||||
|
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToLimitCenterPoses);
|
||||||
|
} else {
|
||||||
|
// Blend IK chains toward the UnderPoses, so some of the animaton motion is present in the IK solution.
|
||||||
|
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses);
|
||||||
|
}
|
||||||
|
|
||||||
// if the hips or the feet are being controlled.
|
// if the hips or the feet are being controlled.
|
||||||
if (hipsEnabled || rightFootEnabled || leftFootEnabled) {
|
if (hipsEnabled || rightFootEnabled || leftFootEnabled) {
|
||||||
// for more predictable IK solve from the center of the joint limits, not from the underpose
|
|
||||||
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToLimitCenterPoses);
|
|
||||||
|
|
||||||
// replace the feet animation with the default pose, this is to prevent unexpected toe wiggling.
|
// replace the feet animation with the default pose, this is to prevent unexpected toe wiggling.
|
||||||
_animVars.set("defaultPoseOverlayAlpha", 1.0f);
|
_animVars.set("defaultPoseOverlayAlpha", 1.0f);
|
||||||
_animVars.set("defaultPoseOverlayBoneSet", (int)AnimOverlay::BothFeetBoneSet);
|
_animVars.set("defaultPoseOverlayBoneSet", (int)AnimOverlay::BothFeetBoneSet);
|
||||||
} else {
|
} else {
|
||||||
// augment the IK with the underPose.
|
|
||||||
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses);
|
|
||||||
|
|
||||||
// feet should follow source animation
|
// feet should follow source animation
|
||||||
_animVars.unset("defaultPoseOverlayAlpha");
|
_animVars.unset("defaultPoseOverlayAlpha");
|
||||||
_animVars.unset("defaultPoseOverlayBoneSet");
|
_animVars.unset("defaultPoseOverlayBoneSet");
|
||||||
|
|
|
@ -55,6 +55,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::gl::GLBackend::do_setUniformBuffer),
|
(&::gpu::gl::GLBackend::do_setUniformBuffer),
|
||||||
(&::gpu::gl::GLBackend::do_setResourceBuffer),
|
(&::gpu::gl::GLBackend::do_setResourceBuffer),
|
||||||
(&::gpu::gl::GLBackend::do_setResourceTexture),
|
(&::gpu::gl::GLBackend::do_setResourceTexture),
|
||||||
|
(&::gpu::gl::GLBackend::do_setResourceTextureTable),
|
||||||
(&::gpu::gl::GLBackend::do_setResourceFramebufferSwapChainTexture),
|
(&::gpu::gl::GLBackend::do_setResourceFramebufferSwapChainTexture),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_setFramebuffer),
|
(&::gpu::gl::GLBackend::do_setFramebuffer),
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Let these be configured by the one define picked above
|
// Let these be configured by the one define picked above
|
||||||
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
#ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
|
||||||
#define GPU_STEREO_DRAWCALL_DOUBLED
|
#define GPU_STEREO_DRAWCALL_DOUBLED
|
||||||
|
@ -102,6 +101,12 @@ public:
|
||||||
static const int MAX_NUM_RESOURCE_TEXTURES = 16;
|
static const int MAX_NUM_RESOURCE_TEXTURES = 16;
|
||||||
size_t getMaxNumResourceTextures() const { return MAX_NUM_RESOURCE_TEXTURES; }
|
size_t getMaxNumResourceTextures() const { return MAX_NUM_RESOURCE_TEXTURES; }
|
||||||
|
|
||||||
|
// Texture Tables offers 2 dedicated slot (taken from the ubo slots)
|
||||||
|
static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2;
|
||||||
|
static const int RESOURCE_TABLE_TEXTURE_SLOT_OFFSET = TRANSFORM_CAMERA_SLOT + 1;
|
||||||
|
size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; }
|
||||||
|
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
|
virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
|
||||||
virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
|
virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
|
||||||
|
@ -130,6 +135,7 @@ public:
|
||||||
// Resource Stage
|
// Resource Stage
|
||||||
virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
|
||||||
|
virtual void do_setResourceTextureTable(const Batch& batch, size_t paramOffset);
|
||||||
virtual void do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
|
@ -230,6 +236,10 @@ protected:
|
||||||
|
|
||||||
void recycle() const override;
|
void recycle() const override;
|
||||||
|
|
||||||
|
// FIXME instead of a single flag, create a features struct similar to
|
||||||
|
// https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPhysicalDeviceFeatures.html
|
||||||
|
virtual bool supportsBindless() const { return false; }
|
||||||
|
|
||||||
static const size_t INVALID_OFFSET = (size_t)-1;
|
static const size_t INVALID_OFFSET = (size_t)-1;
|
||||||
bool _inRenderTransferPass { false };
|
bool _inRenderTransferPass { false };
|
||||||
int32_t _uboAlignment { 0 };
|
int32_t _uboAlignment { 0 };
|
||||||
|
@ -389,6 +399,10 @@ protected:
|
||||||
virtual bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) = 0;
|
virtual bool bindResourceBuffer(uint32_t slot, BufferPointer& buffer) = 0;
|
||||||
virtual void releaseResourceBuffer(uint32_t slot) = 0;
|
virtual void releaseResourceBuffer(uint32_t slot) = 0;
|
||||||
|
|
||||||
|
// Helper function that provides common code used by do_setResourceTexture and
|
||||||
|
// do_setResourceTextureTable (in non-bindless mode)
|
||||||
|
void bindResourceTexture(uint32_t slot, const TexturePointer& texture);
|
||||||
|
|
||||||
// update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s
|
// update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s
|
||||||
void releaseResourceTexture(uint32_t slot);
|
void releaseResourceTexture(uint32_t slot);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//
|
//
|
||||||
// GLBackendPipeline.cpp
|
// GLBackendPipeline.cpp
|
||||||
// libraries/gpu/src/gpu
|
// libraries/gpu/src/gpu
|
||||||
//
|
//
|
||||||
|
@ -9,6 +9,8 @@
|
||||||
// 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 "GLBackend.h"
|
#include "GLBackend.h"
|
||||||
|
#include <gpu/TextureTable.h>
|
||||||
|
|
||||||
#include "GLShared.h"
|
#include "GLShared.h"
|
||||||
#include "GLPipeline.h"
|
#include "GLPipeline.h"
|
||||||
#include "GLShader.h"
|
#include "GLShader.h"
|
||||||
|
@ -247,8 +249,11 @@ void GLBackend::do_setResourceTexture(const Batch& batch, size_t paramOffset) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePointer resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
|
const auto& resourceTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
|
||||||
|
bindResourceTexture(slot, resourceTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::bindResourceTexture(uint32_t slot, const TexturePointer& resourceTexture) {
|
||||||
if (!resourceTexture) {
|
if (!resourceTexture) {
|
||||||
releaseResourceTexture(slot);
|
releaseResourceTexture(slot);
|
||||||
return;
|
return;
|
||||||
|
@ -306,6 +311,19 @@ void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& reso
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setResourceTextureTable(const Batch& batch, size_t paramOffset) {
|
||||||
|
const auto& textureTablePointer = batch._textureTables.get(batch._params[paramOffset]._uint);
|
||||||
|
if (!textureTablePointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& textureTable = *textureTablePointer;
|
||||||
|
const auto& textures = textureTable.getTextures();
|
||||||
|
for (GLuint slot = 0; slot < textures.size(); ++slot) {
|
||||||
|
bindResourceTexture(slot, textures[slot]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int GLBackend::ResourceStageState::findEmptyTextureSlot() const {
|
int GLBackend::ResourceStageState::findEmptyTextureSlot() const {
|
||||||
// start from the end of the slots, try to find an empty one that can be used
|
// start from the end of the slots, try to find an empty one that can be used
|
||||||
for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) {
|
for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) {
|
||||||
|
@ -315,4 +333,3 @@ int GLBackend::ResourceStageState::findEmptyTextureSlot() const {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,11 @@ R"SHADER(
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TextureTable specific defines
|
||||||
|
static const std::string textureTableVersion {
|
||||||
|
"#extension GL_ARB_bindless_texture : require\n#define GPU_TEXTURE_TABLE_BINDLESS\n"
|
||||||
|
};
|
||||||
|
|
||||||
// Versions specific of the shader
|
// Versions specific of the shader
|
||||||
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
static const std::array<std::string, GLShader::NumVersions> VERSION_DEFINES { {
|
||||||
"",
|
"",
|
||||||
|
@ -96,9 +101,9 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::Co
|
||||||
auto& shaderObject = shaderObjects[version];
|
auto& shaderObject = shaderObjects[version];
|
||||||
|
|
||||||
std::string shaderDefines = getBackendShaderHeader() + "\n"
|
std::string shaderDefines = getBackendShaderHeader() + "\n"
|
||||||
|
+ (supportsBindless() ? textureTableVersion : "\n")
|
||||||
+ DOMAIN_DEFINES[shader.getType()] + "\n"
|
+ DOMAIN_DEFINES[shader.getType()] + "\n"
|
||||||
+ VERSION_DEFINES[version];
|
+ VERSION_DEFINES[version];
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
bool retest = true;
|
bool retest = true;
|
||||||
std::string currentSrc = shaderSource;
|
std::string currentSrc = shaderSource;
|
||||||
|
@ -120,7 +125,7 @@ GLShader* GLBackend::compileBackendShader(const Shader& shader, const Shader::Co
|
||||||
compilationLogs[version].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, compilationLogs[version].message);
|
compilationLogs[version].compiled = ::gl::compileShader(shaderDomain, shaderSource, shaderDefines, shaderObject.glshader, compilationLogs[version].message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compilationLogs[version].compiled) {
|
if (!compilationLogs[version].compiled) {
|
||||||
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[version].message.c_str();
|
qCWarning(gpugllogging) << "GLBackend::compileBackendProgram - Shader didn't compile:\n" << compilationLogs[version].message.c_str();
|
||||||
shader.setCompilationLogs(compilationLogs);
|
shader.setCompilationLogs(compilationLogs);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -167,7 +167,6 @@ void GL41Texture::syncSampler() const {
|
||||||
glTexParameteri(_target, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
glTexParameteri(_target, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, (uint16)sampler.getMipOffset());
|
|
||||||
|
|
||||||
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
@ -206,9 +205,6 @@ void GL41FixedAllocationTexture::allocateStorage() const {
|
||||||
void GL41FixedAllocationTexture::syncSampler() const {
|
void GL41FixedAllocationTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), sampler.getMinMip());
|
|
||||||
|
|
||||||
glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, baseMip);
|
|
||||||
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTexParameterf(_target, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.0f : sampler.getMaxMip()));
|
glTexParameterf(_target, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.0f : sampler.getMaxMip()));
|
||||||
}
|
}
|
||||||
|
@ -610,4 +606,3 @@ GL41ResourceTexture::GL41ResourceTexture(const std::weak_ptr<GLBackend>& backend
|
||||||
|
|
||||||
GL41ResourceTexture::~GL41ResourceTexture() {
|
GL41ResourceTexture::~GL41ResourceTexture() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
#include <gpu/gl/GLTexture.h>
|
#include <gpu/gl/GLTexture.h>
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <gpu/TextureTable.h>
|
||||||
|
|
||||||
#define INCREMENTAL_TRANSFER 0
|
#define INCREMENTAL_TRANSFER 0
|
||||||
#define GPU_SSBO_TRANSFORM_OBJECT 1
|
#define GPU_SSBO_TRANSFORM_OBJECT 1
|
||||||
|
#define GPU_BINDLESS_TEXTURES 0
|
||||||
|
|
||||||
namespace gpu { namespace gl45 {
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
@ -31,6 +33,9 @@ class GL45Backend : public GLBackend {
|
||||||
friend class Context;
|
friend class Context;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
virtual bool supportsBindless() const override { return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
||||||
static const GLint TRANSFORM_OBJECT_SLOT { 14 }; // SSBO binding slot
|
static const GLint TRANSFORM_OBJECT_SLOT { 14 }; // SSBO binding slot
|
||||||
|
@ -58,8 +63,62 @@ public:
|
||||||
void generateMips() const override;
|
void generateMips() const override;
|
||||||
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
||||||
void syncSampler() const override;
|
void syncSampler() const override;
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
bool isBindless() const {
|
||||||
|
return _bindless.operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bindless {
|
||||||
|
uint64_t handle{ 0 };
|
||||||
|
uint32_t minMip{ 0 };
|
||||||
|
uint32_t sampler{ 0 };
|
||||||
|
|
||||||
|
bool operator==(const Bindless& other) const {
|
||||||
|
return handle == other.handle && minMip == other.minMip && sampler == other.sampler;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Bindless& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const {
|
||||||
|
return handle != 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual const Bindless& getBindless() const;
|
||||||
|
void releaseBindless() const;
|
||||||
|
void recreateBindless() const;
|
||||||
|
private:
|
||||||
|
mutable Bindless _bindless;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Sampler getInvalidSampler();
|
||||||
|
|
||||||
|
// This stores the texture handle (64 bits) in xy, the min mip available in z, and the sampler ID in w
|
||||||
|
mutable Sampler _cachedSampler{ getInvalidSampler() };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
class GL45TextureTable : public GLObject<TextureTable> {
|
||||||
|
static GLuint allocate();
|
||||||
|
using Parent = GLObject<TextureTable>;
|
||||||
|
public:
|
||||||
|
using BindlessArray = std::array<GL45Texture::Bindless, TextureTable::COUNT>;
|
||||||
|
|
||||||
|
GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& texture);
|
||||||
|
~GL45TextureTable();
|
||||||
|
|
||||||
|
void update(const BindlessArray& newHandles);
|
||||||
|
|
||||||
|
// FIXME instead of making a buffer for each table, there should be a global buffer of all materials
|
||||||
|
// and we should store an offset into that buffer
|
||||||
|
BindlessArray _handles;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Textures that have fixed allocation sizes and cannot be managed at runtime
|
// Textures that have fixed allocation sizes and cannot be managed at runtime
|
||||||
//
|
//
|
||||||
|
@ -74,6 +133,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Size size() const override { return _size; }
|
Size size() const override { return _size; }
|
||||||
|
|
||||||
void allocateStorage() const;
|
void allocateStorage() const;
|
||||||
void syncSampler() const override;
|
void syncSampler() const override;
|
||||||
const Size _size { 0 };
|
const Size _size { 0 };
|
||||||
|
@ -104,7 +164,6 @@ public:
|
||||||
friend class GL45Backend;
|
friend class GL45Backend;
|
||||||
using PromoteLambda = std::function<void()>;
|
using PromoteLambda = std::function<void()>;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture);
|
||||||
~GL45VariableAllocationTexture();
|
~GL45VariableAllocationTexture();
|
||||||
|
@ -114,6 +173,9 @@ public:
|
||||||
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
Size copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const override;
|
||||||
void copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) override;
|
void copyTextureMipsInGPUMem(GLuint srcId, GLuint destId, uint16_t srcMipOffset, uint16_t destMipOffset, uint16_t populatedMips) override;
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
virtual const Bindless& getBindless() const override;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class GL45ResourceTexture : public GL45VariableAllocationTexture {
|
class GL45ResourceTexture : public GL45VariableAllocationTexture {
|
||||||
|
@ -182,6 +244,7 @@ protected:
|
||||||
GLuint getQueryID(const QueryPointer& query) override;
|
GLuint getQueryID(const QueryPointer& query) override;
|
||||||
GLQuery* syncGPUObject(const Query& query) override;
|
GLQuery* syncGPUObject(const Query& query) override;
|
||||||
|
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
void do_draw(const Batch& batch, size_t paramOffset) override;
|
void do_draw(const Batch& batch, size_t paramOffset) override;
|
||||||
void do_drawIndexed(const Batch& batch, size_t paramOffset) override;
|
void do_drawIndexed(const Batch& batch, size_t paramOffset) override;
|
||||||
|
@ -213,6 +276,12 @@ protected:
|
||||||
|
|
||||||
// Texture Management Stage
|
// Texture Management Stage
|
||||||
void initTextureManagementStage() override;
|
void initTextureManagementStage() override;
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
GL45TextureTable* syncGPUObject(const TextureTablePointer& textureTable);
|
||||||
|
// Resource stage
|
||||||
|
void do_setResourceTextureTable(const Batch& batch, size_t paramOffset) override;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -165,6 +165,11 @@ void GL45Backend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loc = glGetUniformBlockIndex(glprogram, "gpu_resourceTextureTable0");
|
||||||
|
if (loc >= 0) {
|
||||||
|
glUniformBlockBinding(glprogram, loc, RESOURCE_TABLE_TEXTURE_SLOT_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,17 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
#include <gl/Context.h>
|
||||||
|
#include <gpu/TextureTable.h>
|
||||||
#include <gpu/gl/GLTexelFormat.h>
|
#include <gpu/gl/GLTexelFormat.h>
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
#define SPARSE_PAGE_SIZE_OVERHEAD_ESTIMATE 1.3f
|
|
||||||
#define MAX_RESOURCE_TEXTURES_PER_FRAME 2
|
#define MAX_RESOURCE_TEXTURES_PER_FRAME 2
|
||||||
|
#define FORCE_STRICT_TEXTURE 0
|
||||||
|
#define ENABLE_SPARSE_TEXTURE 0
|
||||||
|
|
||||||
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
if (!texturePointer) {
|
if (!texturePointer) {
|
||||||
|
@ -51,14 +54,18 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
object = new GL45AttachmentTexture(shared_from_this(), texture);
|
object = new GL45AttachmentTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if FORCE_STRICT_TEXTURE
|
||||||
|
case TextureUsageType::RESOURCE:
|
||||||
|
#endif
|
||||||
case TextureUsageType::STRICT_RESOURCE:
|
case TextureUsageType::STRICT_RESOURCE:
|
||||||
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
qCDebug(gpugllogging) << "Strict texture " << texture.source().c_str();
|
||||||
object = new GL45StrictResourceTexture(shared_from_this(), texture);
|
object = new GL45StrictResourceTexture(shared_from_this(), texture);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if !FORCE_STRICT_TEXTURE
|
||||||
case TextureUsageType::RESOURCE: {
|
case TextureUsageType::RESOURCE: {
|
||||||
if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) {
|
if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) {
|
||||||
#if 0
|
#if ENABLE_SPARSE_TEXTURE
|
||||||
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
||||||
object = new GL45SparseResourceTexture(shared_from_this(), texture);
|
object = new GL45SparseResourceTexture(shared_from_this(), texture);
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,7 +83,7 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -114,6 +121,61 @@ void GL45Backend::initTextureManagementStage() {
|
||||||
|
|
||||||
using GL45Texture = GL45Backend::GL45Texture;
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
|
|
||||||
|
|
||||||
|
class GLSamplerCache {
|
||||||
|
public:
|
||||||
|
GLuint getGLSampler(const Sampler& sampler) {
|
||||||
|
if (0 == _samplerCache.count(sampler)) {
|
||||||
|
GLuint result = 0;
|
||||||
|
glGenSamplers(1, &result);
|
||||||
|
const auto& fm = GLTexture::FILTER_MODES[sampler.getFilter()];
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
||||||
|
if (sampler.doComparison()) {
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE_ARB);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_FUNC, COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||||
|
} else {
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_S, GLTexture::WRAP_MODES[sampler.getWrapModeU()]);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_T, GLTexture::WRAP_MODES[sampler.getWrapModeV()]);
|
||||||
|
glSamplerParameteri(result, GL_TEXTURE_WRAP_R, GLTexture::WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
|
glSamplerParameterfv(result, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
|
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MIN_LOD, sampler.getMinMip());
|
||||||
|
glSamplerParameterf(result, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
_samplerCache[sampler] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _samplerCache[sampler];
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseGLSampler(GLuint sampler) {
|
||||||
|
// NO OP
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Sampler, GLuint> _samplerCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLSamplerCache SAMPLER_CACHE;
|
||||||
|
|
||||||
|
|
||||||
|
Sampler GL45Texture::getInvalidSampler() {
|
||||||
|
static Sampler INVALID_SAMPLER;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, [] {
|
||||||
|
Sampler::Desc invalidDesc;
|
||||||
|
invalidDesc._borderColor = vec4(-1.0f);
|
||||||
|
INVALID_SAMPLER = Sampler(invalidDesc);
|
||||||
|
});
|
||||||
|
return INVALID_SAMPLER;
|
||||||
|
}
|
||||||
|
|
||||||
GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture)
|
GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture& texture)
|
||||||
: GLTexture(backend, texture, allocate(texture)) {
|
: GLTexture(backend, texture, allocate(texture)) {
|
||||||
}
|
}
|
||||||
|
@ -121,10 +183,10 @@ GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
|
||||||
GLuint GL45Texture::allocate(const Texture& texture) {
|
GLuint GL45Texture::allocate(const Texture& texture) {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
glCreateTextures(getGLTextureType(texture), 1, &result);
|
glCreateTextures(getGLTextureType(texture), 1, &result);
|
||||||
#ifdef DEBUG
|
if (::gl::Context::enableDebugLogger()) {
|
||||||
auto source = texture.source();
|
auto source = texture.source();
|
||||||
glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data());
|
glObjectLabel(GL_TEXTURE, result, (GLsizei)source.length(), source.data());
|
||||||
#endif
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +251,50 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
||||||
return amountCopied;
|
return amountCopied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
void GL45Texture::releaseBindless() const {
|
||||||
|
// Release the old handler
|
||||||
|
SAMPLER_CACHE.releaseGLSampler(_bindless.sampler);
|
||||||
|
glMakeTextureHandleNonResidentARB(_bindless.handle);
|
||||||
|
_bindless = Bindless();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Texture::recreateBindless() const {
|
||||||
|
if (isBindless()) {
|
||||||
|
releaseBindless();
|
||||||
|
} else {
|
||||||
|
// Once a texture is about to become bindless, it's base mip level MUST be set to 0
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bindless.sampler = SAMPLER_CACHE.getGLSampler(_cachedSampler);
|
||||||
|
_bindless.handle = glGetTextureSamplerHandleARB(_id, _bindless.sampler);
|
||||||
|
glMakeTextureHandleResidentARB(_bindless.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GL45Texture::Bindless& GL45Texture::getBindless() const {
|
||||||
|
if (!_bindless) {
|
||||||
|
recreateBindless();
|
||||||
|
}
|
||||||
|
return _bindless;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void GL45Texture::syncSampler() const {
|
void GL45Texture::syncSampler() const {
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
|
if (_cachedSampler == sampler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedSampler = sampler;
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
if (isBindless()) {
|
||||||
|
recreateBindless();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const auto& fm = FILTER_MODES[sampler.getFilter()];
|
const auto& fm = FILTER_MODES[sampler.getFilter()];
|
||||||
glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
@ -214,6 +318,8 @@ void GL45Texture::syncSampler() const {
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fixed allocation textures, used for strict resources & framebuffer attachments
|
||||||
|
|
||||||
using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture;
|
using GL45FixedAllocationTexture = GL45Backend::GL45FixedAllocationTexture;
|
||||||
|
|
||||||
GL45FixedAllocationTexture::GL45FixedAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture), _size(texture.evalTotalSize()) {
|
GL45FixedAllocationTexture::GL45FixedAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture), _size(texture.evalTotalSize()) {
|
||||||
|
@ -238,8 +344,6 @@ void GL45FixedAllocationTexture::allocateStorage() const {
|
||||||
void GL45FixedAllocationTexture::syncSampler() const {
|
void GL45FixedAllocationTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
const Sampler& sampler = _gpuObject.getSampler();
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), sampler.getMinMip());
|
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip);
|
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
}
|
}
|
||||||
|
@ -275,6 +379,9 @@ GL45StrictResourceTexture::GL45StrictResourceTexture(const std::weak_ptr<GLBacke
|
||||||
if (texture.isAutogenerateMips()) {
|
if (texture.isAutogenerateMips()) {
|
||||||
generateMips();
|
generateMips();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-sync the sampler to force access to the new mip level
|
||||||
|
syncSampler();
|
||||||
}
|
}
|
||||||
|
|
||||||
GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
||||||
|
@ -282,3 +389,87 @@ GL45StrictResourceTexture::~GL45StrictResourceTexture() {
|
||||||
Backend::textureResidentGPUMemSize.update(size(), 0);
|
Backend::textureResidentGPUMemSize.update(size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encapsulate bindless textures
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
using GL45TextureTable = GL45Backend::GL45TextureTable;
|
||||||
|
|
||||||
|
GLuint GL45TextureTable::allocate() {
|
||||||
|
GLuint result;
|
||||||
|
glCreateBuffers(1, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL45TextureTable::GL45TextureTable(const std::weak_ptr<GLBackend>& backend, const TextureTable& textureTable)
|
||||||
|
: Parent(backend, textureTable, allocate()){
|
||||||
|
Backend::setGPUObject(textureTable, this);
|
||||||
|
// FIXME include these in overall buffer storage reporting
|
||||||
|
glNamedBufferStorage(_id, sizeof(uvec4) * TextureTable::COUNT, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45TextureTable::update(const BindlessArray& handles) {
|
||||||
|
if (_handles != handles) {
|
||||||
|
_handles = handles;
|
||||||
|
// FIXME include these in overall buffer storage reporting
|
||||||
|
// FIXME use a single shared buffer for bindless data
|
||||||
|
glNamedBufferSubData(_id, 0, sizeof(GL45Texture::Bindless) * TextureTable::COUNT, &_handles[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL45TextureTable::~GL45TextureTable() {
|
||||||
|
if (_id) {
|
||||||
|
auto backend = _backend.lock();
|
||||||
|
if (backend) {
|
||||||
|
// FIXME include these in overall buffer storage reporting
|
||||||
|
backend->releaseBuffer(_id, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GL45TextureTable* GL45Backend::syncGPUObject(const TextureTablePointer& textureTablePointer) {
|
||||||
|
const auto& textureTable = *textureTablePointer;
|
||||||
|
|
||||||
|
// Find the target handles
|
||||||
|
auto defaultTextures = gpu::TextureTable::getDefault()->getTextures();
|
||||||
|
auto textures = textureTable.getTextures();
|
||||||
|
GL45TextureTable::BindlessArray handles{};
|
||||||
|
for (size_t i = 0; i < textures.size(); ++i) {
|
||||||
|
auto texture = textures[i];
|
||||||
|
if (!texture) {
|
||||||
|
texture = defaultTextures[i];
|
||||||
|
}
|
||||||
|
if (!texture) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// FIXME what if we have a non-transferrable texture here?
|
||||||
|
auto gltexture = (GL45Texture*)syncGPUObject(texture);
|
||||||
|
if (!gltexture) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handles[i] = gltexture->getBindless();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the object hasn't been created, or the object definition is out of date, drop and re-create
|
||||||
|
GL45TextureTable* object = Backend::getGPUObject<GL45TextureTable>(textureTable);
|
||||||
|
|
||||||
|
if (!object) {
|
||||||
|
object = new GL45TextureTable(shared_from_this(), textureTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->update(handles);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_setResourceTextureTable(const Batch& batch, size_t paramOffset) {
|
||||||
|
auto textureTablePointer = batch._textureTables.get(batch._params[paramOffset]._uint);
|
||||||
|
if (!textureTablePointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto slot = batch._params[paramOffset + 1]._uint;
|
||||||
|
GL45TextureTable* glTextureTable = syncGPUObject(textureTablePointer);
|
||||||
|
if (glTextureTable) {
|
||||||
|
glBindBufferBase(GL_UNIFORM_BUFFER, slot + GLBackend::RESOURCE_TABLE_TEXTURE_SLOT_OFFSET, glTextureTable->_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ using namespace gpu;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
using GL45VariableAllocationTexture = GL45Backend::GL45VariableAllocationTexture;
|
using GL45VariableAllocationTexture = GL45Backend::GL45VariableAllocationTexture;
|
||||||
|
|
||||||
GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture) {
|
GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture) {
|
||||||
|
@ -40,6 +41,17 @@ GL45VariableAllocationTexture::~GL45VariableAllocationTexture() {
|
||||||
Backend::textureResourcePopulatedGPUMemSize.update(_populatedSize, 0);
|
Backend::textureResourcePopulatedGPUMemSize.update(_populatedSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
const GL45Texture::Bindless& GL45VariableAllocationTexture::getBindless() const {
|
||||||
|
// The parent call may re-initialize the _bindless member, so we need to call it first
|
||||||
|
const auto& result = Parent::getBindless();
|
||||||
|
// Make sure the referenced structure has the correct minimum available mip value
|
||||||
|
_bindless.minMip = _populatedMip - _allocatedMip;
|
||||||
|
// Now return the result
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Size GL45VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
Size GL45VariableAllocationTexture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
||||||
Size amountCopied = 0;
|
Size amountCopied = 0;
|
||||||
amountCopied = Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer);
|
amountCopied = Parent::copyMipFaceLinesFromTexture(mip, face, size, yOffset, internalFormat, format, type, sourceSize, sourcePointer);
|
||||||
|
@ -127,7 +139,13 @@ Size GL45ResourceTexture::copyMipsFromTexture() {
|
||||||
|
|
||||||
void GL45ResourceTexture::syncSampler() const {
|
void GL45ResourceTexture::syncSampler() const {
|
||||||
Parent::syncSampler();
|
Parent::syncSampler();
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
if (!isBindless()) {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
|
||||||
|
}
|
||||||
|
#else
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45ResourceTexture::promote() {
|
void GL45ResourceTexture::promote() {
|
||||||
|
@ -137,6 +155,13 @@ void GL45ResourceTexture::promote() {
|
||||||
uint16_t targetAllocatedMip = _allocatedMip - std::min<uint16_t>(_allocatedMip, 2);
|
uint16_t targetAllocatedMip = _allocatedMip - std::min<uint16_t>(_allocatedMip, 2);
|
||||||
targetAllocatedMip = std::max<uint16_t>(_minAllocatedMip, targetAllocatedMip);
|
targetAllocatedMip = std::max<uint16_t>(_minAllocatedMip, targetAllocatedMip);
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
bool bindless = isBindless();
|
||||||
|
if (bindless) {
|
||||||
|
releaseBindless();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GLuint oldId = _id;
|
GLuint oldId = _id;
|
||||||
auto oldSize = _size;
|
auto oldSize = _size;
|
||||||
uint16_t oldAllocatedMip = _allocatedMip;
|
uint16_t oldAllocatedMip = _allocatedMip;
|
||||||
|
@ -150,10 +175,17 @@ void GL45ResourceTexture::promote() {
|
||||||
// copy pre-existing mips
|
// copy pre-existing mips
|
||||||
copyTextureMipsInGPUMem(oldId, _id, oldAllocatedMip, _allocatedMip, _populatedMip);
|
copyTextureMipsInGPUMem(oldId, _id, oldAllocatedMip, _allocatedMip, _populatedMip);
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
if (bindless) {
|
||||||
|
getBindless();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// destroy the old texture
|
// destroy the old texture
|
||||||
glDeleteTextures(1, &oldId);
|
glDeleteTextures(1, &oldId);
|
||||||
|
|
||||||
// Update sampler
|
// Update sampler
|
||||||
|
_cachedSampler = getInvalidSampler();
|
||||||
syncSampler();
|
syncSampler();
|
||||||
|
|
||||||
// update the memory usage
|
// update the memory usage
|
||||||
|
@ -170,6 +202,13 @@ void GL45ResourceTexture::demote() {
|
||||||
auto oldSize = _size;
|
auto oldSize = _size;
|
||||||
auto oldPopulatedMip = _populatedMip;
|
auto oldPopulatedMip = _populatedMip;
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
bool bindless = isBindless();
|
||||||
|
if (bindless) {
|
||||||
|
releaseBindless();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// allocate new texture
|
// allocate new texture
|
||||||
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
const_cast<GLuint&>(_id) = allocate(_gpuObject);
|
||||||
uint16_t oldAllocatedMip = _allocatedMip;
|
uint16_t oldAllocatedMip = _allocatedMip;
|
||||||
|
@ -179,10 +218,17 @@ void GL45ResourceTexture::demote() {
|
||||||
// copy pre-existing mips
|
// copy pre-existing mips
|
||||||
copyTextureMipsInGPUMem(oldId, _id, oldAllocatedMip, _allocatedMip, _populatedMip);
|
copyTextureMipsInGPUMem(oldId, _id, oldAllocatedMip, _allocatedMip, _populatedMip);
|
||||||
|
|
||||||
|
#if GPU_BINDLESS_TEXTURES
|
||||||
|
if (bindless) {
|
||||||
|
getBindless();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// destroy the old texture
|
// destroy the old texture
|
||||||
glDeleteTextures(1, &oldId);
|
glDeleteTextures(1, &oldId);
|
||||||
|
|
||||||
// Update sampler
|
// Update sampler
|
||||||
|
_cachedSampler = getInvalidSampler();
|
||||||
syncSampler();
|
syncSampler();
|
||||||
|
|
||||||
// update the memory usage
|
// update the memory usage
|
||||||
|
|
|
@ -75,6 +75,7 @@ Batch::Batch(const Batch& batch_) {
|
||||||
|
|
||||||
_buffers._items.swap(batch._buffers._items);
|
_buffers._items.swap(batch._buffers._items);
|
||||||
_textures._items.swap(batch._textures._items);
|
_textures._items.swap(batch._textures._items);
|
||||||
|
_textureTables._items.swap(batch._textureTables._items);
|
||||||
_streamFormats._items.swap(batch._streamFormats._items);
|
_streamFormats._items.swap(batch._streamFormats._items);
|
||||||
_transforms._items.swap(batch._transforms._items);
|
_transforms._items.swap(batch._transforms._items);
|
||||||
_pipelines._items.swap(batch._pipelines._items);
|
_pipelines._items.swap(batch._pipelines._items);
|
||||||
|
@ -113,6 +114,7 @@ void Batch::clear() {
|
||||||
_data.clear();
|
_data.clear();
|
||||||
_buffers.clear();
|
_buffers.clear();
|
||||||
_textures.clear();
|
_textures.clear();
|
||||||
|
_textureTables.clear();
|
||||||
_streamFormats.clear();
|
_streamFormats.clear();
|
||||||
_transforms.clear();
|
_transforms.clear();
|
||||||
_pipelines.clear();
|
_pipelines.clear();
|
||||||
|
@ -337,6 +339,12 @@ void Batch::setResourceTexture(uint32 slot, const TextureView& view) {
|
||||||
setResourceTexture(slot, view._texture);
|
setResourceTexture(slot, view._texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::setResourceTextureTable(const TextureTablePointer& textureTable, uint32 slot) {
|
||||||
|
ADD_COMMAND(setResourceTextureTable);
|
||||||
|
_params.emplace_back(_textureTables.cache(textureTable));
|
||||||
|
_params.emplace_back(slot);
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::setResourceFramebufferSwapChainTexture(uint32 slot, const FramebufferSwapChainPointer& framebuffer, unsigned int swapChainIndex, unsigned int renderBufferSlot) {
|
void Batch::setResourceFramebufferSwapChainTexture(uint32 slot, const FramebufferSwapChainPointer& framebuffer, unsigned int swapChainIndex, unsigned int renderBufferSlot) {
|
||||||
ADD_COMMAND(setResourceFramebufferSwapChainTexture);
|
ADD_COMMAND(setResourceFramebufferSwapChainTexture);
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ public:
|
||||||
|
|
||||||
void setResourceTexture(uint32 slot, const TexturePointer& texture);
|
void setResourceTexture(uint32 slot, const TexturePointer& texture);
|
||||||
void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
|
void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
|
||||||
|
void setResourceTextureTable(const TextureTablePointer& table, uint32 slot = 0);
|
||||||
void setResourceFramebufferSwapChainTexture(uint32 slot, const FramebufferSwapChainPointer& framebuffer, unsigned int swpaChainIndex, unsigned int renderBufferSlot = 0U); // not a command, just a shortcut from a TextureView
|
void setResourceFramebufferSwapChainTexture(uint32 slot, const FramebufferSwapChainPointer& framebuffer, unsigned int swpaChainIndex, unsigned int renderBufferSlot = 0U); // not a command, just a shortcut from a TextureView
|
||||||
|
|
||||||
// Ouput Stage
|
// Ouput Stage
|
||||||
|
@ -302,6 +303,7 @@ public:
|
||||||
COMMAND_setUniformBuffer,
|
COMMAND_setUniformBuffer,
|
||||||
COMMAND_setResourceBuffer,
|
COMMAND_setResourceBuffer,
|
||||||
COMMAND_setResourceTexture,
|
COMMAND_setResourceTexture,
|
||||||
|
COMMAND_setResourceTextureTable,
|
||||||
COMMAND_setResourceFramebufferSwapChainTexture,
|
COMMAND_setResourceFramebufferSwapChainTexture,
|
||||||
|
|
||||||
COMMAND_setFramebuffer,
|
COMMAND_setFramebuffer,
|
||||||
|
@ -409,9 +411,10 @@ public:
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data get(uint32 offset) const {
|
const Data& get(uint32 offset) const {
|
||||||
if (offset >= _items.size()) {
|
if (offset >= _items.size()) {
|
||||||
return Data();
|
static const Data EMPTY;
|
||||||
|
return EMPTY;
|
||||||
}
|
}
|
||||||
return (_items.data() + offset)->_data;
|
return (_items.data() + offset)->_data;
|
||||||
}
|
}
|
||||||
|
@ -424,6 +427,7 @@ public:
|
||||||
|
|
||||||
typedef Cache<BufferPointer>::Vector BufferCaches;
|
typedef Cache<BufferPointer>::Vector BufferCaches;
|
||||||
typedef Cache<TexturePointer>::Vector TextureCaches;
|
typedef Cache<TexturePointer>::Vector TextureCaches;
|
||||||
|
typedef Cache<TextureTablePointer>::Vector TextureTableCaches;
|
||||||
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
|
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
|
||||||
typedef Cache<Transform>::Vector TransformCaches;
|
typedef Cache<Transform>::Vector TransformCaches;
|
||||||
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
typedef Cache<PipelinePointer>::Vector PipelineCaches;
|
||||||
|
@ -479,6 +483,7 @@ public:
|
||||||
|
|
||||||
BufferCaches _buffers;
|
BufferCaches _buffers;
|
||||||
TextureCaches _textures;
|
TextureCaches _textures;
|
||||||
|
TextureTableCaches _textureTables;
|
||||||
StreamFormatCaches _streamFormats;
|
StreamFormatCaches _streamFormats;
|
||||||
TransformCaches _transforms;
|
TransformCaches _transforms;
|
||||||
PipelineCaches _pipelines;
|
PipelineCaches _pipelines;
|
||||||
|
|
|
@ -91,6 +91,8 @@ namespace gpu {
|
||||||
using Textures = std::vector<TexturePointer>;
|
using Textures = std::vector<TexturePointer>;
|
||||||
class TextureView;
|
class TextureView;
|
||||||
using TextureViews = std::vector<TextureView>;
|
using TextureViews = std::vector<TextureView>;
|
||||||
|
class TextureTable;
|
||||||
|
using TextureTablePointer = std::shared_ptr<TextureTable>;
|
||||||
|
|
||||||
struct StereoState {
|
struct StereoState {
|
||||||
bool isStereo() const {
|
bool isStereo() const {
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <shared/Storage.h>
|
#include <shared/Storage.h>
|
||||||
#include <shared/FileCache.h>
|
#include <shared/FileCache.h>
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "Metric.h"
|
#include "Metric.h"
|
||||||
|
@ -126,12 +128,23 @@ public:
|
||||||
uint8 _wrapModeV = WRAP_REPEAT;
|
uint8 _wrapModeV = WRAP_REPEAT;
|
||||||
uint8 _wrapModeW = WRAP_REPEAT;
|
uint8 _wrapModeW = WRAP_REPEAT;
|
||||||
|
|
||||||
uint8 _mipOffset = 0;
|
|
||||||
uint8 _minMip = 0;
|
uint8 _minMip = 0;
|
||||||
uint8 _maxMip = MAX_MIP_LEVEL;
|
uint8 _maxMip = MAX_MIP_LEVEL;
|
||||||
|
|
||||||
Desc() {}
|
Desc() {}
|
||||||
Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {}
|
Desc(const Filter filter, const WrapMode wrap = WRAP_REPEAT) : _filter(filter), _wrapModeU(wrap), _wrapModeV(wrap), _wrapModeW(wrap) {}
|
||||||
|
|
||||||
|
bool operator==(const Desc& other) const {
|
||||||
|
return _borderColor == other._borderColor &&
|
||||||
|
_maxAnisotropy == other._maxAnisotropy &&
|
||||||
|
_filter == other._filter &&
|
||||||
|
_comparisonFunc == other._comparisonFunc &&
|
||||||
|
_wrapModeU == other._wrapModeU &&
|
||||||
|
_wrapModeV == other._wrapModeV &&
|
||||||
|
_wrapModeW == other._wrapModeW &&
|
||||||
|
_minMip == other._minMip &&
|
||||||
|
_maxMip == other._maxMip;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Sampler() {}
|
Sampler() {}
|
||||||
|
@ -151,11 +164,17 @@ public:
|
||||||
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
|
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
|
||||||
bool doComparison() const { return getComparisonFunction() != ALWAYS; }
|
bool doComparison() const { return getComparisonFunction() != ALWAYS; }
|
||||||
|
|
||||||
uint8 getMipOffset() const { return _desc._mipOffset; }
|
|
||||||
uint8 getMinMip() const { return _desc._minMip; }
|
uint8 getMinMip() const { return _desc._minMip; }
|
||||||
uint8 getMaxMip() const { return _desc._maxMip; }
|
uint8 getMaxMip() const { return _desc._maxMip; }
|
||||||
|
|
||||||
const Desc& getDesc() const { return _desc; }
|
const Desc& getDesc() const { return _desc; }
|
||||||
|
|
||||||
|
bool operator==(const Sampler& other) const {
|
||||||
|
return _desc == other._desc;
|
||||||
|
}
|
||||||
|
bool operator!=(const Sampler& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Desc _desc;
|
Desc _desc;
|
||||||
};
|
};
|
||||||
|
@ -666,6 +685,17 @@ typedef std::shared_ptr< TextureSource > TextureSourcePointer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<> struct hash<gpu::Sampler> {
|
||||||
|
size_t operator()(const gpu::Sampler& sampler) const noexcept {
|
||||||
|
size_t result = 0;
|
||||||
|
const auto& desc = sampler.getDesc();
|
||||||
|
hash_combine(result, desc._comparisonFunc, desc._filter, desc._maxAnisotropy, desc._maxMip, desc._minMip, desc._wrapModeU, desc._wrapModeV, desc._wrapModeW);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(gpu::TexturePointer)
|
Q_DECLARE_METATYPE(gpu::TexturePointer)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
54
libraries/gpu/src/gpu/TextureTable.cpp
Normal file
54
libraries/gpu/src/gpu/TextureTable.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2017/01/25
|
||||||
|
// Copyright 2013-2017 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 "TextureTable.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
using namespace gpu;
|
||||||
|
|
||||||
|
|
||||||
|
const size_t TextureTable::COUNT{ TEXTURE_TABLE_COUNT };
|
||||||
|
|
||||||
|
TextureTable::TextureTable() { }
|
||||||
|
|
||||||
|
TextureTable::TextureTable(const std::initializer_list<TexturePointer>& textures) {
|
||||||
|
auto max = std::min<size_t>(COUNT, textures.size());
|
||||||
|
auto itr = textures.begin();
|
||||||
|
size_t index = 0;
|
||||||
|
while (itr != textures.end() && index < max) {
|
||||||
|
setTexture(index, *itr);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureTable::TextureTable(const Array& textures) : _textures(textures) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureTable::setTexture(size_t index, const TexturePointer& texturePointer) {
|
||||||
|
if (index >= COUNT || _textures[index] == texturePointer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Lock lock(_mutex);
|
||||||
|
++_stamp;
|
||||||
|
_textures[index] = texturePointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureTable::setTexture(size_t index, const TextureView& textureView) {
|
||||||
|
setTexture(index, textureView._texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureTable::Array TextureTable::getTextures() const {
|
||||||
|
Array result;
|
||||||
|
{
|
||||||
|
Lock lock(_mutex);
|
||||||
|
result = _textures;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
44
libraries/gpu/src/gpu/TextureTable.h
Normal file
44
libraries/gpu/src/gpu/TextureTable.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2017/01/25
|
||||||
|
// Copyright 2013-2017 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_TextureTable_h
|
||||||
|
#define hifi_gpu_TextureTable_h
|
||||||
|
|
||||||
|
#include "Forward.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#define TEXTURE_TABLE_COUNT 8
|
||||||
|
|
||||||
|
namespace gpu {
|
||||||
|
|
||||||
|
class TextureTable {
|
||||||
|
public:
|
||||||
|
static const size_t COUNT;
|
||||||
|
using Array = std::array<TexturePointer, TEXTURE_TABLE_COUNT>;
|
||||||
|
TextureTable();
|
||||||
|
TextureTable(const std::initializer_list<TexturePointer>& textures);
|
||||||
|
TextureTable(const Array& textures);
|
||||||
|
|
||||||
|
// Only for gpu::Context
|
||||||
|
const GPUObjectPointer gpuObject{};
|
||||||
|
|
||||||
|
void setTexture(size_t index, const TexturePointer& texturePointer);
|
||||||
|
void setTexture(size_t index, const TextureView& texturePointer);
|
||||||
|
|
||||||
|
Array getTextures() const;
|
||||||
|
Stamp getStamp() const { return _stamp; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable Mutex _mutex;
|
||||||
|
Array _textures;
|
||||||
|
Stamp _stamp{ 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
38
libraries/gpu/src/gpu/TextureTable.slh
Normal file
38
libraries/gpu/src/gpu/TextureTable.slh
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<!
|
||||||
|
// gpu/TextureTable.slh
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 1/25/17.
|
||||||
|
// Copyright 2013 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
|
||||||
|
!>
|
||||||
|
<@if not GPU_TEXTURE_TABLE_SLH@>
|
||||||
|
<@def GPU_TEXTURE_TABLE_SLH@>
|
||||||
|
|
||||||
|
#ifdef GPU_TEXTURE_TABLE_BINDLESS
|
||||||
|
#define GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES 8
|
||||||
|
|
||||||
|
struct GPUTextureTable {
|
||||||
|
uvec4 _textures[GPU_TEXTURE_TABLE_MAX_NUM_TEXTURES];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TextureTable(index, name) layout (std140) uniform gpu_resourceTextureTable##index { GPUTextureTable name; }
|
||||||
|
|
||||||
|
#define tableTex(name, slot) sampler2D(name._textures[slot].xy)
|
||||||
|
#define tableTexMinLod(name, slot) float(name._textures[slot].z)
|
||||||
|
|
||||||
|
#define tableTexValue(name, slot, uv) \
|
||||||
|
tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)
|
||||||
|
|
||||||
|
vec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {
|
||||||
|
float queryLod = textureQueryLod(sampler, uv).x;
|
||||||
|
queryLod = max(minLod, queryLod);
|
||||||
|
return textureLod(sampler, uv, queryLod);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
<@endif@>
|
|
@ -504,6 +504,8 @@ TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) {
|
||||||
gpuktxKeyValue._usage = Texture::Usage::Builder().withColor().withAlpha().build();
|
gpuktxKeyValue._usage = Texture::Usage::Builder().withColor().withAlpha().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto samplerDesc = gpuktxKeyValue._samplerDesc;
|
||||||
|
samplerDesc._maxMip = gpu::Sampler::MAX_MIP_LEVEL;
|
||||||
auto texture = create(gpuktxKeyValue._usageType,
|
auto texture = create(gpuktxKeyValue._usageType,
|
||||||
type,
|
type,
|
||||||
texelFormat,
|
texelFormat,
|
||||||
|
@ -513,7 +515,7 @@ TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) {
|
||||||
1, // num Samples
|
1, // num Samples
|
||||||
header.getNumberOfSlices(),
|
header.getNumberOfSlices(),
|
||||||
header.getNumberOfLevels(),
|
header.getNumberOfLevels(),
|
||||||
gpuktxKeyValue._samplerDesc);
|
samplerDesc);
|
||||||
texture->setUsage(gpuktxKeyValue._usage);
|
texture->setUsage(gpuktxKeyValue._usage);
|
||||||
|
|
||||||
// Assing the mips availables
|
// Assing the mips availables
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <ColorUtils.h>
|
#include <ColorUtils.h>
|
||||||
|
|
||||||
#include <gpu/Resource.h>
|
#include <gpu/Resource.h>
|
||||||
|
#include <gpu/TextureTable.h>
|
||||||
|
|
||||||
class Transform;
|
class Transform;
|
||||||
|
|
||||||
|
@ -361,6 +362,8 @@ public:
|
||||||
const std::string& getModel() const { return _model; }
|
const std::string& getModel() const { return _model; }
|
||||||
void setModel(const std::string& model) { _model = model; }
|
void setModel(const std::string& model) { _model = model; }
|
||||||
|
|
||||||
|
const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string _name { "" };
|
std::string _name { "" };
|
||||||
|
|
||||||
|
@ -368,6 +371,7 @@ private:
|
||||||
mutable MaterialKey _key;
|
mutable MaterialKey _key;
|
||||||
mutable UniformBufferView _schemaBuffer;
|
mutable UniformBufferView _schemaBuffer;
|
||||||
mutable UniformBufferView _texMapArrayBuffer;
|
mutable UniformBufferView _texMapArrayBuffer;
|
||||||
|
mutable gpu::TextureTablePointer _textureTable{ std::make_shared<gpu::TextureTable>() };
|
||||||
|
|
||||||
TextureMaps _textureMaps;
|
TextureMaps _textureMaps;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,74 @@ TexMapArray getTexMapArray() {
|
||||||
|
|
||||||
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion, withScattering)@>
|
||||||
|
|
||||||
|
<@include gpu/TextureTable.slh@>
|
||||||
|
|
||||||
|
#ifdef GPU_TEXTURE_TABLE_BINDLESS
|
||||||
|
|
||||||
|
TextureTable(0, matTex);
|
||||||
|
<!
|
||||||
|
ALBEDO = 0,
|
||||||
|
NORMAL, 1
|
||||||
|
METALLIC, 2
|
||||||
|
EMISSIVE_LIGHTMAP, 3
|
||||||
|
ROUGHNESS, 4
|
||||||
|
OCCLUSION, 5
|
||||||
|
SCATTERING, 6
|
||||||
|
!>
|
||||||
|
|
||||||
|
<@if withAlbedo@>
|
||||||
|
#define albedoMap 0
|
||||||
|
vec4 fetchAlbedoMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, albedoMap, uv);
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withRoughness@>
|
||||||
|
#define roughnessMap 4
|
||||||
|
float fetchRoughnessMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, roughnessMap, uv).r;
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withNormal@>
|
||||||
|
#define normalMap 1
|
||||||
|
vec3 fetchNormalMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, normalMap, uv).xyz;
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withMetallic@>
|
||||||
|
#define metallicMap 2
|
||||||
|
float fetchMetallicMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, metallicMap, uv).r;
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withEmissive@>
|
||||||
|
#define emissiveMap 3
|
||||||
|
vec3 fetchEmissiveMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, emissiveMap, uv).rgb;
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withOcclusion@>
|
||||||
|
#define occlusionMap 5
|
||||||
|
float fetchOcclusionMap(vec2 uv) {
|
||||||
|
return tableTexValue(matTex, occlusionMap, uv).r;
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
<@if withScattering@>
|
||||||
|
#define scatteringMap 6
|
||||||
|
float fetchScatteringMap(vec2 uv) {
|
||||||
|
float scattering = texture(tableTex(matTex, scatteringMap), uv).r; // boolean scattering for now
|
||||||
|
return max(((scattering - 0.1) / 0.9), 0.0);
|
||||||
|
return tableTexValue(matTex, scatteringMap, uv).r; // boolean scattering for now
|
||||||
|
}
|
||||||
|
<@endif@>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
<@if withAlbedo@>
|
<@if withAlbedo@>
|
||||||
uniform sampler2D albedoMap;
|
uniform sampler2D albedoMap;
|
||||||
vec4 fetchAlbedoMap(vec2 uv) {
|
vec4 fetchAlbedoMap(vec2 uv) {
|
||||||
|
@ -102,6 +170,8 @@ float fetchScatteringMap(vec2 uv) {
|
||||||
}
|
}
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) {
|
||||||
batch.setInputStream(0, _drawMesh->getVertexStream());
|
batch.setInputStream(0, _drawMesh->getVertexStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const {
|
void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const {
|
||||||
batch.setModelTransform(_drawTransform);
|
batch.setModelTransform(_drawTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -612,7 +612,8 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) {
|
||||||
#include "RenderPipelines.h"
|
#include "RenderPipelines.h"
|
||||||
#include <model-networking/TextureCache.h>
|
#include <model-networking/TextureCache.h>
|
||||||
|
|
||||||
void RenderPipelines::bindMaterial(graphics::MaterialPointer material, gpu::Batch& batch, bool enableTextures) {
|
// FIXME find a better way to setup the default textures
|
||||||
|
void RenderPipelines::bindMaterial(const graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures) {
|
||||||
if (!material) {
|
if (!material) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -630,84 +631,65 @@ void RenderPipelines::bindMaterial(graphics::MaterialPointer material, gpu::Batc
|
||||||
numUnlit++;
|
numUnlit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enableTextures) {
|
const auto& drawMaterialTextures = material->getTextureTable();
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getWhiteTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture());
|
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Albedo
|
// Albedo
|
||||||
if (materialKey.isAlbedoMap()) {
|
if (materialKey.isAlbedoMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView());
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::ALBEDO, textureCache->getWhiteTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roughness map
|
// Roughness map
|
||||||
if (materialKey.isRoughnessMap()) {
|
if (materialKey.isRoughnessMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::ROUGHNESS, itr->second->getTextureView());
|
||||||
|
|
||||||
// texcoord are assumed to be the same has albedo
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::ROUGHNESS, textureCache->getWhiteTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal map
|
// Normal map
|
||||||
if (materialKey.isNormalMap()) {
|
if (materialKey.isNormalMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::NORMAL, itr->second->getTextureView());
|
||||||
|
|
||||||
// texcoord are assumed to be the same has albedo
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::NORMAL, textureCache->getBlueTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metallic map
|
// Metallic map
|
||||||
if (materialKey.isMetallicMap()) {
|
if (materialKey.isMetallicMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::METALLIC, itr->second->getTextureView());
|
||||||
|
|
||||||
// texcoord are assumed to be the same has albedo
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::METALLIC, textureCache->getBlackTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Occlusion map
|
// Occlusion map
|
||||||
if (materialKey.isOcclusionMap()) {
|
if (materialKey.isOcclusionMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::OCCLUSION, itr->second->getTextureView());
|
||||||
|
|
||||||
// texcoord are assumed to be the same has albedo
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::OCCLUSION, textureCache->getWhiteTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scattering map
|
// Scattering map
|
||||||
if (materialKey.isScatteringMap()) {
|
if (materialKey.isScatteringMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP);
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::SCATTERING, itr->second->getTextureView());
|
||||||
|
|
||||||
// texcoord are assumed to be the same has albedo
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::SCATTERING, textureCache->getWhiteTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,18 +697,19 @@ void RenderPipelines::bindMaterial(graphics::MaterialPointer material, gpu::Batc
|
||||||
if (materialKey.isLightmapMap()) {
|
if (materialKey.isLightmapMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP);
|
||||||
|
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture());
|
||||||
}
|
}
|
||||||
} else if (materialKey.isEmissiveMap()) {
|
} else if (materialKey.isEmissiveMap()) {
|
||||||
auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP);
|
auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP);
|
||||||
|
if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {
|
||||||
if (itr != textureMaps.end() && itr->second->isDefined()) {
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView());
|
|
||||||
} else {
|
} else {
|
||||||
batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture());
|
drawMaterialTextures->setTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.setResourceTextureTable(material->getTextureTable());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
class RenderPipelines {
|
class RenderPipelines {
|
||||||
public:
|
public:
|
||||||
static void bindMaterial(graphics::MaterialPointer material, gpu::Batch& batch, bool enableTextures);
|
static void bindMaterial(const graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,14 +89,8 @@
|
||||||
bubbleOverlayTimestamp = nowTimestamp;
|
bubbleOverlayTimestamp = nowTimestamp;
|
||||||
Script.update.connect(update);
|
Script.update.connect(update);
|
||||||
updateConnected = true;
|
updateConnected = true;
|
||||||
|
writeButtonProperties(bubbleButtonFlashState);
|
||||||
// Flash button
|
bubbleButtonFlashState = !bubbleButtonFlashState;
|
||||||
if (!bubbleFlashTimer) {
|
|
||||||
bubbleFlashTimer = Script.setInterval(function () {
|
|
||||||
writeButtonProperties(bubbleButtonFlashState);
|
|
||||||
bubbleButtonFlashState = !bubbleButtonFlashState;
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from the C++ scripting interface to show the bubble overlay
|
// Called from the C++ scripting interface to show the bubble overlay
|
||||||
|
|
Loading…
Reference in a new issue