From 99ef2735b74196d62921563f430beee6a055032e Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Tue, 2 Nov 2021 16:16:37 -0700 Subject: [PATCH 01/35] Create download UI once and update existing UI with progress Signed-off-by: AMZN-Phil --- .../Source/DownloadController.cpp | 8 +- .../Source/DownloadController.h | 6 +- .../GemCatalog/GemCatalogHeaderWidget.cpp | 185 +++++++++++------- .../GemCatalog/GemCatalogHeaderWidget.h | 10 + .../Source/GemCatalog/GemCatalogScreen.cpp | 5 +- 5 files changed, 141 insertions(+), 73 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index 224b90299c..00a7db5318 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -41,6 +41,8 @@ namespace O3DE::ProjectManager void DownloadController::AddGemDownload(const QString& gemName) { m_gemNames.push_back(gemName); + emit GemDownloadAdded(gemName); + if (m_gemNames.size() == 1) { m_worker->SetGemToDownload(m_gemNames[0], false); @@ -62,6 +64,7 @@ namespace O3DE::ProjectManager else { m_gemNames.erase(findResult); + emit GemDownloadRemoved(gemName); } } } @@ -69,7 +72,7 @@ namespace O3DE::ProjectManager void DownloadController::UpdateUIProgress(int progress) { m_lastProgress = progress; - emit GemDownloadProgress(progress); + emit GemDownloadProgress(*m_gemNames.begin(), progress); } void DownloadController::HandleResults(const QString& result) @@ -82,8 +85,9 @@ namespace O3DE::ProjectManager succeeded = false; } + QString gemName = *m_gemNames.begin(); m_gemNames.erase(m_gemNames.begin()); - emit Done(succeeded); + emit Done(gemName, succeeded); if (!m_gemNames.empty()) { diff --git a/Code/Tools/ProjectManager/Source/DownloadController.h b/Code/Tools/ProjectManager/Source/DownloadController.h index 11ceaacddb..0bf0ae473c 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.h +++ b/Code/Tools/ProjectManager/Source/DownloadController.h @@ -58,8 +58,10 @@ namespace O3DE::ProjectManager signals: void StartGemDownload(const QString& gemName); - void Done(bool success = true); - void GemDownloadProgress(int percentage); + void Done(const QString& gemName, bool success = true); + void GemDownloadAdded(const QString& gemName); + void GemDownloadRemoved(const QString& gemName); + void GemDownloadProgress(const QString& gemName, int percentage); private: DownloadWorker* m_worker; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index 5d65c740af..cfe69283ff 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -30,6 +30,7 @@ namespace O3DE::ProjectManager m_layout->setMargin(5); m_layout->setAlignment(Qt::AlignTop); setLayout(m_layout); + setMinimumHeight(400); QHBoxLayout* hLayout = new QHBoxLayout(); @@ -119,6 +120,12 @@ namespace O3DE::ProjectManager setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); } + CartOverlayWidget::~CartOverlayWidget() + { + // disconnect from all download controller signals + disconnect(m_downloadController, nullptr, this, nullptr); + } + void CartOverlayWidget::CreateGemSection(const QString& singularTitle, const QString& pluralTitle, GetTagIndicesCallback getTagIndices) { QWidget* widget = new QWidget(); @@ -162,13 +169,13 @@ namespace O3DE::ProjectManager void CartOverlayWidget::CreateDownloadSection() { - QWidget* widget = new QWidget(); - widget->setFixedWidth(s_width); - m_layout->addWidget(widget); + m_downloadSectionWidget = new QWidget(); + m_downloadSectionWidget->setFixedWidth(s_width); + m_layout->addWidget(m_downloadSectionWidget); QVBoxLayout* layout = new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); - widget->setLayout(layout); + m_downloadSectionWidget->setLayout(layout); QLabel* titleLabel = new QLabel(); titleLabel->setObjectName("GemCatalogCartOverlaySectionLabel"); @@ -187,82 +194,126 @@ namespace O3DE::ProjectManager QLabel* processingQueueLabel = new QLabel("Processing Queue"); gemDownloadLayout->addWidget(processingQueueLabel); - QWidget* downloadingItemWidget = new QWidget(); - downloadingItemWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG"); - gemDownloadLayout->addWidget(downloadingItemWidget); + m_downloadingListWidget = new QWidget(); + m_downloadingListWidget->setObjectName("GemCatalogCartOverlayGemDownloadBG"); + gemDownloadLayout->addWidget(m_downloadingListWidget); QVBoxLayout* downloadingItemLayout = new QVBoxLayout(); downloadingItemLayout->setAlignment(Qt::AlignTop); - downloadingItemWidget->setLayout(downloadingItemLayout); + m_downloadingListWidget->setLayout(downloadingItemLayout); - auto update = [=](int downloadProgress) + QLabel* downloadsInProgessLabel = new QLabel(""); + downloadsInProgessLabel->setObjectName("NumDownloadsInProgressLabel"); + downloadingItemLayout->addWidget(downloadsInProgessLabel); + + if (m_downloadController->IsDownloadQueueEmpty()) + { + m_downloadSectionWidget->hide(); + } + else { - if (m_downloadController->IsDownloadQueueEmpty()) + // Setup gem download rows for gems that are already in the queue + const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); + + for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber) { - widget->hide(); + GemDownloadAdded(downloadQueue[downloadingGemNumber]); } - else - { - widget->setUpdatesEnabled(false); - // remove items - QLayoutItem* layoutItem = nullptr; - while ((layoutItem = downloadingItemLayout->takeAt(0)) != nullptr) - { - if (layoutItem->layout()) - { - // Gem info row - QLayoutItem* rowLayoutItem = nullptr; - while ((rowLayoutItem = layoutItem->layout()->takeAt(0)) != nullptr) - { - rowLayoutItem->widget()->deleteLater(); - } - layoutItem->layout()->deleteLater(); - } - if (layoutItem->widget()) - { - layoutItem->widget()->deleteLater(); - } - } + } - // Setup gem download rows - const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); + // connect to download controller data changed + connect(m_downloadController, &DownloadController::GemDownloadAdded, this, &CartOverlayWidget::GemDownloadAdded); + connect(m_downloadController, &DownloadController::GemDownloadRemoved, this, &CartOverlayWidget::GemDownloadRemoved); + connect(m_downloadController, &DownloadController::GemDownloadProgress, this, &CartOverlayWidget::GemDownloadProgress); + connect(m_downloadController, &DownloadController::Done, this, &CartOverlayWidget::GemDownloadComplete); + } - QLabel* downloadsInProgessLabel = new QLabel(""); - downloadsInProgessLabel->setText( - QString("%1 %2").arg(downloadQueue.size()).arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress..."))); - downloadingItemLayout->addWidget(downloadsInProgessLabel); + void CartOverlayWidget::GemDownloadAdded(const QString& gemName) + { + QWidget* newGemDownloadWidget = new QWidget(); + newGemDownloadWidget->setObjectName(gemName); + QVBoxLayout* downloadingGemLayout = new QVBoxLayout(); + newGemDownloadWidget->setLayout(downloadingGemLayout); + QHBoxLayout* nameProgressLayout = new QHBoxLayout(); + TagWidget* newTag = new TagWidget(gemName); + nameProgressLayout->addWidget(newTag); + QLabel* progress = new QLabel(tr("Queued")); + progress->setObjectName("DownloadProgressLabel"); + nameProgressLayout->addWidget(progress); + QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + nameProgressLayout->addSpacerItem(spacer); + QLabel* cancelText = new QLabel(QString("Cancel").arg(gemName)); + cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); + connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); + nameProgressLayout->addWidget(cancelText); + downloadingGemLayout->addLayout(nameProgressLayout); + QProgressBar* downloadProgessBar = new QProgressBar(); + downloadProgessBar->setObjectName("DownloadProgressBar"); + downloadingGemLayout->addWidget(downloadProgessBar); + downloadProgessBar->setValue(0); + + m_downloadingListWidget->layout()->addWidget(newGemDownloadWidget); + + const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); + QLabel* numDownloads = m_downloadingListWidget->findChild("NumDownloadsInProgressLabel"); + numDownloads->setText(QString("%1 %2") + .arg(downloadQueue.size()) + .arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress..."))); + + m_downloadingListWidget->show(); + } - for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber) - { - QHBoxLayout* nameProgressLayout = new QHBoxLayout(); - TagWidget* newTag = new TagWidget(downloadQueue[downloadingGemNumber]); - nameProgressLayout->addWidget(newTag); - QLabel* progress = new QLabel(downloadingGemNumber == 0? QString("%1%").arg(downloadProgress) : tr("Queued")); - nameProgressLayout->addWidget(progress); - QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); - nameProgressLayout->addSpacerItem(spacer); - QLabel* cancelText = new QLabel(QString("Cancel").arg(downloadQueue[downloadingGemNumber])); - cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); - connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); - nameProgressLayout->addWidget(cancelText); - downloadingItemLayout->addLayout(nameProgressLayout); - QProgressBar* downloadProgessBar = new QProgressBar(); - downloadingItemLayout->addWidget(downloadProgessBar); - downloadProgessBar->setValue(downloadingGemNumber == 0 ? downloadProgress : 0); - } + void CartOverlayWidget::GemDownloadRemoved(const QString& gemName) + { + QWidget* gemToRemove = m_downloadingListWidget->findChild(gemName); + QLayout* gemToRemoveLayout = gemToRemove ? gemToRemove->layout() : nullptr; - widget->setUpdatesEnabled(true); - widget->show(); + if (gemToRemoveLayout) + { + QLayoutItem* rowLayoutItem = nullptr; + while ((rowLayoutItem = gemToRemoveLayout->layout()->takeAt(0)) != nullptr) + { + rowLayoutItem->widget()->deleteLater(); } - }; + gemToRemoveLayout->layout()->deleteLater(); + gemToRemove->deleteLater(); + } - auto downloadEnded = [=](bool /*success*/) + const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); + + if (m_downloadController->IsDownloadQueueEmpty()) { - update(0); // update the list to remove the gem that has finished - }; - // connect to download controller data changed - connect(m_downloadController, &DownloadController::GemDownloadProgress, this, update); - connect(m_downloadController, &DownloadController::Done, this, downloadEnded); - update(0); + m_downloadSectionWidget->hide(); + } + else + { + QLabel* numDownloads = m_downloadingListWidget->findChild("NumDownloadsInProgressLabel"); + numDownloads->setText(QString("%1 %2") + .arg(downloadQueue.size()) + .arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress..."))); + } + } + + void CartOverlayWidget::GemDownloadProgress(const QString& gemName, int percentage) + { + QWidget* gemToUpdate = m_downloadingListWidget->findChild(gemName); + if (gemToUpdate) + { + QLabel* progressLabel = gemToUpdate->findChild("DownloadProgressLabel"); + if (progressLabel) + { + progressLabel->setText(QString("%1%").arg(percentage)); + } + QProgressBar* progressBar = gemToUpdate->findChild("DownloadProgressBar"); + if (progressBar) + { + progressBar->setValue(percentage); + } + } + } + + void CartOverlayWidget::GemDownloadComplete(const QString& gemName, bool /*success*/) + { + GemDownloadRemoved(gemName); // update the list to remove the gem that has finished } QStringList CartOverlayWidget::ConvertFromModelIndices(const QVector& gems) const diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h index 4d17259840..a8f50a5338 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.h @@ -34,6 +34,13 @@ namespace O3DE::ProjectManager public: CartOverlayWidget(GemModel* gemModel, DownloadController* downloadController, QWidget* parent = nullptr); + ~CartOverlayWidget(); + + public slots: + void GemDownloadAdded(const QString& gemName); + void GemDownloadRemoved(const QString& gemName); + void GemDownloadProgress(const QString& gemName, int percentage); + void GemDownloadComplete(const QString& gemName, bool success); private: QStringList ConvertFromModelIndices(const QVector& gems) const; @@ -47,6 +54,9 @@ namespace O3DE::ProjectManager GemModel* m_gemModel = nullptr; DownloadController* m_downloadController = nullptr; + QWidget* m_downloadSectionWidget = nullptr; + QWidget* m_downloadingListWidget = nullptr; + inline constexpr static int s_width = 240; }; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index a22f41d054..32cf35c04d 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -145,7 +145,7 @@ namespace O3DE::ProjectManager } } - void GemCatalogScreen::OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies) + void GemCatalogScreen::OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies) { if (m_notificationsEnabled) { @@ -170,6 +170,7 @@ namespace O3DE::ProjectManager if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded) { m_downloadController->AddGemDownload(GemModel::GetName(modelIndex)); + GemModel::SetDownloadStatus(*m_proxModel, modelIndex, GemInfo::DownloadStatus::Downloading); } } @@ -187,7 +188,7 @@ namespace O3DE::ProjectManager toastConfiguration.m_customIconImage = ":/gem.svg"; toastConfiguration.m_borderRadius = 4; toastConfiguration.m_duration = AZStd::chrono::milliseconds(3000); - m_notificationsView->ShowToastNotification(toastConfiguration); + //m_notificationsView->ShowToastNotification(toastConfiguration); } } From 9d977e81da0b9d4c3135ad6f0d8e5aa9aec2298e Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Thu, 4 Nov 2021 15:20:35 -0700 Subject: [PATCH 02/35] Uncomment temporary disabling of toast notifications Signed-off-by: AMZN-Phil --- .../Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 32cf35c04d..db34375db5 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -188,7 +188,7 @@ namespace O3DE::ProjectManager toastConfiguration.m_customIconImage = ":/gem.svg"; toastConfiguration.m_borderRadius = 4; toastConfiguration.m_duration = AZStd::chrono::milliseconds(3000); - //m_notificationsView->ShowToastNotification(toastConfiguration); + m_notificationsView->ShowToastNotification(toastConfiguration); } } From c6e77f8e32c35d33fa639a00c6aea819b360ffbc Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Fri, 5 Nov 2021 14:21:10 -0700 Subject: [PATCH 03/35] Code readability improvements Signed-off-by: AMZN-Phil --- .../Source/DownloadController.cpp | 8 ++-- .../GemCatalog/GemCatalogHeaderWidget.cpp | 41 ++++++++----------- .../Source/GemCatalog/GemCatalogScreen.cpp | 2 +- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/DownloadController.cpp b/Code/Tools/ProjectManager/Source/DownloadController.cpp index 00a7db5318..6326b2fc11 100644 --- a/Code/Tools/ProjectManager/Source/DownloadController.cpp +++ b/Code/Tools/ProjectManager/Source/DownloadController.cpp @@ -45,7 +45,7 @@ namespace O3DE::ProjectManager if (m_gemNames.size() == 1) { - m_worker->SetGemToDownload(m_gemNames[0], false); + m_worker->SetGemToDownload(m_gemNames.front(), false); m_workerThread.start(); } } @@ -72,7 +72,7 @@ namespace O3DE::ProjectManager void DownloadController::UpdateUIProgress(int progress) { m_lastProgress = progress; - emit GemDownloadProgress(*m_gemNames.begin(), progress); + emit GemDownloadProgress(m_gemNames.front(), progress); } void DownloadController::HandleResults(const QString& result) @@ -85,13 +85,13 @@ namespace O3DE::ProjectManager succeeded = false; } - QString gemName = *m_gemNames.begin(); + QString gemName = m_gemNames.front(); m_gemNames.erase(m_gemNames.begin()); emit Done(gemName, succeeded); if (!m_gemNames.empty()) { - emit StartGemDownload(m_gemNames[0]); + emit StartGemDownload(m_gemNames.front()); } else { diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp index cfe69283ff..b0729c0047 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogHeaderWidget.cpp @@ -214,9 +214,9 @@ namespace O3DE::ProjectManager // Setup gem download rows for gems that are already in the queue const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); - for (int downloadingGemNumber = 0; downloadingGemNumber < downloadQueue.size(); ++downloadingGemNumber) + for (const QString& gemName : downloadQueue) { - GemDownloadAdded(downloadQueue[downloadingGemNumber]); + GemDownloadAdded(gemName); } } @@ -229,24 +229,28 @@ namespace O3DE::ProjectManager void CartOverlayWidget::GemDownloadAdded(const QString& gemName) { + // Containing widget for the current download item QWidget* newGemDownloadWidget = new QWidget(); newGemDownloadWidget->setObjectName(gemName); - QVBoxLayout* downloadingGemLayout = new QVBoxLayout(); + QVBoxLayout* downloadingGemLayout = new QVBoxLayout(newGemDownloadWidget); newGemDownloadWidget->setLayout(downloadingGemLayout); - QHBoxLayout* nameProgressLayout = new QHBoxLayout(); - TagWidget* newTag = new TagWidget(gemName); + + // Gem name, progress string, cancel + QHBoxLayout* nameProgressLayout = new QHBoxLayout(newGemDownloadWidget); + TagWidget* newTag = new TagWidget(gemName, newGemDownloadWidget); nameProgressLayout->addWidget(newTag); - QLabel* progress = new QLabel(tr("Queued")); + QLabel* progress = new QLabel(tr("Queued"), newGemDownloadWidget); progress->setObjectName("DownloadProgressLabel"); nameProgressLayout->addWidget(progress); - QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); - nameProgressLayout->addSpacerItem(spacer); - QLabel* cancelText = new QLabel(QString("Cancel").arg(gemName)); + nameProgressLayout->addStretch(); + QLabel* cancelText = new QLabel(tr("Cancel").arg(gemName), newGemDownloadWidget); cancelText->setTextInteractionFlags(Qt::LinksAccessibleByMouse); connect(cancelText, &QLabel::linkActivated, this, &CartOverlayWidget::OnCancelDownloadActivated); nameProgressLayout->addWidget(cancelText); downloadingGemLayout->addLayout(nameProgressLayout); - QProgressBar* downloadProgessBar = new QProgressBar(); + + // Progress bar + QProgressBar* downloadProgessBar = new QProgressBar(newGemDownloadWidget); downloadProgessBar->setObjectName("DownloadProgressBar"); downloadingGemLayout->addWidget(downloadProgessBar); downloadProgessBar->setValue(0); @@ -265,31 +269,22 @@ namespace O3DE::ProjectManager void CartOverlayWidget::GemDownloadRemoved(const QString& gemName) { QWidget* gemToRemove = m_downloadingListWidget->findChild(gemName); - QLayout* gemToRemoveLayout = gemToRemove ? gemToRemove->layout() : nullptr; - - if (gemToRemoveLayout) + if (gemToRemove) { - QLayoutItem* rowLayoutItem = nullptr; - while ((rowLayoutItem = gemToRemoveLayout->layout()->takeAt(0)) != nullptr) - { - rowLayoutItem->widget()->deleteLater(); - } - gemToRemoveLayout->layout()->deleteLater(); gemToRemove->deleteLater(); } - const AZStd::vector& downloadQueue = m_downloadController->GetDownloadQueue(); - if (m_downloadController->IsDownloadQueueEmpty()) { m_downloadSectionWidget->hide(); } else { + size_t downloadQueueSize = m_downloadController->GetDownloadQueue().size(); QLabel* numDownloads = m_downloadingListWidget->findChild("NumDownloadsInProgressLabel"); numDownloads->setText(QString("%1 %2") - .arg(downloadQueue.size()) - .arg(downloadQueue.size() == 1 ? tr("download in progress...") : tr("downloads in progress..."))); + .arg(downloadQueueSize) + .arg(downloadQueueSize == 1 ? tr("download in progress...") : tr("downloads in progress..."))); } } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index 9f5d4a70f2..f3e1da011a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -175,7 +175,7 @@ namespace O3DE::ProjectManager if (added && GemModel::GetDownloadStatus(modelIndex) == GemInfo::DownloadStatus::NotDownloaded) { m_downloadController->AddGemDownload(GemModel::GetName(modelIndex)); - GemModel::SetDownloadStatus(*m_proxyModel, modelIndex, GemInfo::DownloadStatus::Downloading); + GemModel::SetDownloadStatus(*m_proxyModel, m_proxyModel->mapFromSource(modelIndex), GemInfo::DownloadStatus::Downloading); } } From 9481f8a488ec26196ae7a04f4ba2b5b114e6e857 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 5 Nov 2021 23:39:34 -0700 Subject: [PATCH 04/35] Updated 002_wrinkle_regression_test.material to avoid subsurface scattering artifacts. Having subsurface scattering into a completely back area is an unrealistic scenario and caused colored artifacts. I changed the material to mask out the black areas from applying SS. Corresponding changes will be made to the expceted screenshot in AtomSampleViewer as well. Note these artifacts were originally introduced at commit 19638c4697a2e95bcb9b12badd82980e92b4c5ac Fri Jul 2 01:18:09 where SS was fixed to work again where it bad previously been broken and didn't show up in this test case. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../SkinTestCases/002_wrinkle_regression_test.material | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material index 400044d29f..78f597b14f 100644 --- a/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material +++ b/Gems/Atom/TestData/TestData/Materials/SkinTestCases/002_wrinkle_regression_test.material @@ -33,7 +33,7 @@ }, "subsurfaceScattering": { "enableSubsurfaceScattering": true, - "influenceMap": "Objects/Lucy/Lucy_thickness.tif", + "influenceMap": "TestData/Textures/checker8x8_gray_512.png", "scatterDistance": 15.0, "subsurfaceScatterFactor": 0.4300000071525574, "thicknessMap": "Objects/Lucy/Lucy_thickness.tif", @@ -47,8 +47,7 @@ 0.3182879388332367, 0.16388189792633058, 1.0 - ], - "useInfluenceMap": false + ] }, "wrinkleLayers": { "baseColorMap1": "TestData/Textures/cc0/Lava004_1K_Color.jpg", @@ -61,4 +60,4 @@ "normalMap2": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_normal.png" } } -} +} \ No newline at end of file From fe005c9c5050cd2e87ecf14719b0f03216ea2e9f Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Mon, 8 Nov 2021 16:11:30 -0700 Subject: [PATCH 05/35] Added exposure controls to the ReflectionProbe component Signed-off-by: dmcdiar --- .../Atom/Features/PBR/DefaultObjectSrg.azsli | 1 + .../Atom/Features/PBR/Lights/Ibl.azsli | 6 +++--- .../Atom/Features/Skin/SkinObjectSrg.azsli | 1 + .../ReflectionProbeRenderInner.azsl | 2 +- .../ReflectionProbeRenderObjectSrg.azsli | 1 + .../ReflectionProbeRenderOuter.azsl | 2 +- .../ReflectionProbeFeatureProcessor.h | 2 ++ ...ReflectionProbeFeatureProcessorInterface.h | 2 ++ .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 4 ++++ .../ReflectionProbe/ReflectionProbe.cpp | 17 ++++++++++++++-- .../Source/ReflectionProbe/ReflectionProbe.h | 11 ++++++++++ .../ReflectionProbeFeatureProcessor.cpp | 12 +++++++++++ .../EditorReflectionProbeComponent.cpp | 20 +++++++++++++++++++ .../EditorReflectionProbeComponent.h | 2 ++ .../ReflectionProbeComponentController.cpp | 19 ++++++++++++++++-- .../ReflectionProbeComponentController.h | 6 ++++++ 16 files changed, 99 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli index 10526597cb..9f40e7ab8f 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli @@ -37,6 +37,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject float m_padding; bool m_useReflectionProbe; bool m_useParallaxCorrection; + float m_exposure; }; ReflectionProbeData m_reflectionProbeData; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index d33a307dfe..31439de144 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -85,12 +85,12 @@ void ApplyIBL(Surface surface, inout LightingData lightingData) if(useIbl) { - float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); + float exposure = pow(2.0, ObjectSrg::m_reflectionProbeData.m_exposure); if(useDiffuseIbl) { float3 iblDiffuse = GetIblDiffuse(surface.normal, surface.albedo, lightingData.diffuseResponse); - lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.diffuseAmbientOcclusion); + lightingData.diffuseLighting += (iblDiffuse * exposure * lightingData.diffuseAmbientOcclusion); } if(useSpecularIbl) @@ -116,7 +116,7 @@ void ApplyIBL(Surface surface, inout LightingData lightingData) iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular; } - lightingData.specularLighting += (iblSpecular * iblExposureFactor); + lightingData.specularLighting += (iblSpecular * exposure); } } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli index d0766c295d..99a32629ef 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli @@ -46,6 +46,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject float m_padding; bool m_useReflectionProbe; bool m_useParallaxCorrection; + float m_exposure; }; ReflectionProbeData m_reflectionProbeData; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl index a0734caf02..e9333a4694 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl @@ -81,7 +81,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) } // apply exposure setting - specular *= pow(2.0, SceneSrg::m_iblExposure); + specular *= pow(2.0, ObjectSrg::m_exposure); PSOutput OUT; OUT.m_color = float4(specular, 1.0f); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli index 8151ed2fd5..366dc691ed 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli @@ -17,6 +17,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject float3 m_outerObbHalfLengths; float3 m_innerObbHalfLengths; bool m_useParallaxCorrection; + float m_exposure; TextureCube m_reflectionCubeMap; float4x4 GetWorldMatrix() diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl index ac97172f1f..138d29398e 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl @@ -104,7 +104,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) blendWeight /= max(1.0f, blendWeightAllProbes); // apply exposure setting - specular *= pow(2.0, SceneSrg::m_iblExposure); + specular *= pow(2.0, ObjectSrg::m_exposure); // apply blend weight for additive blending specular *= blendWeight; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h index 5efd235a67..ded36f5496 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -39,6 +39,8 @@ namespace AZ bool IsCubeMapReferenced(const AZStd::string& relativePath) override; bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); } void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) override; + void SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure) override; + void SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure) override; // FeatureProcessor overrides void Activate() override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h index 4eb2130b1b..80c92281ea 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h @@ -50,6 +50,8 @@ namespace AZ virtual bool IsCubeMapReferenced(const AZStd::string& relativePath) = 0; virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0; virtual void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) = 0; + virtual void SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure) = 0; + virtual void SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure) = 0; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index c7fb19bc5d..99f01ea630 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -1178,6 +1178,9 @@ namespace AZ AZ::RHI::ShaderInputConstantIndex useParallaxCorrectionConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useParallaxCorrection")); AZ_Error("MeshDataInstance", useParallaxCorrectionConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex exposureConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_exposure")); + AZ_Error("MeshDataInstance", exposureConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + // retrieve probe cubemap index Name reflectionCubeMapImageName = Name("m_reflectionProbeCubeMap"); RHI::ShaderInputImageIndex reflectionCubeMapImageIndex = m_shaderResourceGroup->FindShaderInputImageIndex(reflectionCubeMapImageName); @@ -1198,6 +1201,7 @@ namespace AZ m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true); m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection()); + m_shaderResourceGroup->SetConstant(exposureConstantIndex, reflectionProbes[0]->GetRenderExposure()); m_shaderResourceGroup->SetImage(reflectionCubeMapImageIndex, reflectionProbes[0]->GetCubeMapImage()); } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index e86d91d387..c4ea3249d5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -127,8 +127,8 @@ namespace AZ } else { - // set exposure to 0.0 while baking the cubemap - sceneSrg->SetConstant(m_iblExposureConstantIndex, 0.0f); + // set exposure to the user specified value while baking the cubemap + sceneSrg->SetConstant(m_iblExposureConstantIndex, m_bakeExposure); } } @@ -162,6 +162,7 @@ namespace AZ m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_exposureConstantIndex, m_renderExposure); m_renderOuterSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderOuterSrg->Compile(); @@ -172,6 +173,7 @@ namespace AZ m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_exposureConstantIndex, m_renderExposure); m_renderInnerSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderInnerSrg->Compile(); @@ -326,6 +328,17 @@ namespace AZ m_meshFeatureProcessor->SetVisible(m_visualizationMeshHandle, showVisualization); } + void ReflectionProbe::SetRenderExposure(float renderExposure) + { + m_renderExposure = renderExposure; + m_updateSrg = true; + } + + void ReflectionProbe::SetBakeExposure(float bakeExposure) + { + m_bakeExposure = bakeExposure; + } + const RHI::DrawPacket* ReflectionProbe::BuildDrawPacket( const Data::Instance& srg, const RPI::Ptr& pipelineState, diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index bee304c5b9..485f380463 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -61,6 +61,7 @@ namespace AZ RHI::ShaderInputNameIndex m_outerObbHalfLengthsRenderConstantIndex = "m_outerObbHalfLengths"; RHI::ShaderInputNameIndex m_innerObbHalfLengthsRenderConstantIndex = "m_innerObbHalfLengths"; RHI::ShaderInputNameIndex m_useParallaxCorrectionRenderConstantIndex = "m_useParallaxCorrection"; + RHI::ShaderInputNameIndex m_exposureConstantIndex = "m_exposure"; RHI::ShaderInputNameIndex m_reflectionCubeMapRenderImageIndex = "m_reflectionCubeMap"; }; @@ -106,6 +107,14 @@ namespace AZ // enables or disables rendering of the visualization sphere void ShowVisualization(bool showVisualization); + // the exposure to use when rendering meshes with this probe's cubemap + void SetRenderExposure(float renderExposure); + float GetRenderExposure() const { return m_renderExposure; } + + // the exposure to use when baking the probe cubemap + void SetBakeExposure(float bakeExposure); + float GetBakeExposure() const { return m_bakeExposure; } + private: AZ_DISABLE_COPY_MOVE(ReflectionProbe); @@ -157,6 +166,8 @@ namespace AZ RHI::ConstPtr m_blendWeightDrawPacket; RHI::ConstPtr m_renderOuterDrawPacket; RHI::ConstPtr m_renderInnerDrawPacket; + float m_renderExposure = 0.0f; + float m_bakeExposure = 0.0f; bool m_updateSrg = false; const RHI::DrawItemSortKey InvalidSortKey = static_cast(-1); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 52d089ae0d..b1484ac8a8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -283,6 +283,18 @@ namespace AZ probe->ShowVisualization(showVisualization); } + void ReflectionProbeFeatureProcessor::SetRenderExposure(const ReflectionProbeHandle& probe, float renderExposure) + { + AZ_Assert(probe.get(), "SetRenderExposure called with an invalid handle"); + probe->SetRenderExposure(renderExposure); + } + + void ReflectionProbeFeatureProcessor::SetBakeExposure(const ReflectionProbeHandle& probe, float bakeExposure) + { + AZ_Assert(probe.get(), "SetBakeExposure called with an invalid handle"); + probe->SetBakeExposure(bakeExposure); + } + void ReflectionProbeFeatureProcessor::FindReflectionProbes(const Vector3& position, ReflectionProbeVector& reflectionProbes) { reflectionProbes.clear(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index 99e99abf4a..c14d2c320a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -40,6 +40,7 @@ namespace AZ ->Field("bakedCubeMapQualityLevel", &EditorReflectionProbeComponent::m_bakedCubeMapQualityLevel) ->Field("bakedCubeMapRelativePath", &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath) ->Field("authoredCubeMapAsset", &EditorReflectionProbeComponent::m_authoredCubeMapAsset) + ->Field("bakeExposure", &EditorReflectionProbeComponent::m_bakeExposure) ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) @@ -62,6 +63,13 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ButtonText, "Bake Reflection Probe") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::BakeReflectionProbe) ->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting) + ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorReflectionProbeComponent::m_bakeExposure, "Bake Exposure", "Exposure to use when baking the cubemap") + ->Attribute(AZ::Edit::Attributes::SoftMin, -5.0f) + ->Attribute(AZ::Edit::Attributes::SoftMax, 5.0f) + ->Attribute(AZ::Edit::Attributes::Min, -20.0f) + ->Attribute(AZ::Edit::Attributes::Max, 20.0f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnBakeExposureChanged) + ->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting) ->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap") @@ -111,6 +119,11 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &ReflectionProbeComponentConfig::m_showVisualization, "Show Visualization", "Show the reflection probe visualization sphere") ->Attribute(AZ::Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->DataElement(AZ::Edit::UIHandlers::Slider, &ReflectionProbeComponentConfig::m_renderExposure, "Exposure", "Exposure to use when rendering meshes with the cubemap") + ->Attribute(AZ::Edit::Attributes::SoftMin, -5.0f) + ->Attribute(AZ::Edit::Attributes::SoftMax, 5.0f) + ->Attribute(AZ::Edit::Attributes::Min, -20.0f) + ->Attribute(AZ::Edit::Attributes::Max, 20.0f) ; } } @@ -275,6 +288,13 @@ namespace AZ return AZ::Edit::PropertyRefreshLevels::None; } + AZ::u32 EditorReflectionProbeComponent::OnBakeExposureChanged() + { + m_controller.SetBakeExposure(m_bakeExposure); + + return AZ::Edit::PropertyRefreshLevels::None; + } + AZ::u32 EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting() { // controls specific to baked cubemaps call this to determine their visibility diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h index 441da19e78..3cd017fd18 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h @@ -55,6 +55,7 @@ namespace AZ // change notifications AZ::u32 OnUseBakedCubemapChanged(); AZ::u32 OnAuthoredCubemapChanged(); + AZ::u32 OnBakeExposureChanged(); // retrieves visibility for baked or authored cubemap controls AZ::u32 GetBakedCubemapVisibilitySetting(); @@ -77,6 +78,7 @@ namespace AZ AZStd::string m_bakedCubeMapRelativePath; Data::Asset m_bakedCubeMapAsset; Data::Asset m_authoredCubeMapAsset; + float m_bakeExposure = 0.0f; // flag indicating if a cubemap bake is currently in progress AZStd::atomic_bool m_bakeInProgress = false; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index 4022dfda9b..017f6c9cdf 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -35,7 +35,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(0) + ->Version(1) ->Field("OuterHeight", &ReflectionProbeComponentConfig::m_outerHeight) ->Field("OuterLength", &ReflectionProbeComponentConfig::m_outerLength) ->Field("OuterWidth", &ReflectionProbeComponentConfig::m_outerWidth) @@ -49,7 +49,9 @@ namespace AZ ->Field("AuthoredCubeMapAsset", &ReflectionProbeComponentConfig::m_authoredCubeMapAsset) ->Field("EntityId", &ReflectionProbeComponentConfig::m_entityId) ->Field("UseParallaxCorrection", &ReflectionProbeComponentConfig::m_useParallaxCorrection) - ->Field("ShowVisualization", &ReflectionProbeComponentConfig::m_showVisualization); + ->Field("ShowVisualization", &ReflectionProbeComponentConfig::m_showVisualization) + ->Field("RenderExposure", &ReflectionProbeComponentConfig::m_renderExposure) + ->Field("BakeExposure", &ReflectionProbeComponentConfig::m_bakeExposure); } } @@ -157,6 +159,9 @@ namespace AZ cubeMapAsset.QueueLoad(); Data::AssetBus::MultiHandler::BusConnect(cubeMapAsset.GetId()); } + + // set cubemap render exposure + m_featureProcessor->SetRenderExposure(m_handle, m_configuration.m_renderExposure); } void ReflectionProbeComponentController::Deactivate() @@ -284,6 +289,16 @@ namespace AZ m_configuration.m_innerHeight = AZStd::min(m_configuration.m_innerHeight, m_configuration.m_outerHeight); } + void ReflectionProbeComponentController::SetBakeExposure(float bakeExposure) + { + if (!m_featureProcessor) + { + return; + } + + m_featureProcessor->SetBakeExposure(m_handle, bakeExposure); + } + void ReflectionProbeComponentController::BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath) { if (!m_featureProcessor) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h index 18e13f023b..ad7d9f7f53 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h @@ -68,6 +68,9 @@ namespace AZ Data::Asset m_bakedCubeMapAsset; Data::Asset m_authoredCubeMapAsset; AZ::u64 m_entityId{ EntityId::InvalidEntityId }; + + float m_renderExposure = 0.0f; + float m_bakeExposure = 0.0f; }; class ReflectionProbeComponentController final @@ -99,6 +102,9 @@ namespace AZ // returns the outer extent Aabb for this reflection AZ::Aabb GetAabb() const; + // set the exposure to use when baking the cubemap + void SetBakeExposure(float bakeExposure); + // initiate the reflection probe bake, invokes callback when complete void BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath); From 898b1811e0be97b50e9b7845803765fda0635d5f Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 21 Oct 2021 16:04:38 -0500 Subject: [PATCH 06/35] material editor loads source data Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 25 ++- .../RPI.Edit/Material/MaterialSourceData.cpp | 167 +++++++++++++----- .../Material/MaterialTypeAssetCreator.cpp | 1 + .../Code/Source/Document/MaterialDocument.cpp | 2 +- 4 files changed, 151 insertions(+), 44 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index a67477f061..739c4341a9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -31,6 +31,7 @@ namespace AZ static constexpr const char UvGroupName[] = "uvSets"; class MaterialAsset; + class MaterialAssetCreator; //! This is a simple data structure for serializing in/out material source files. class MaterialSourceData final @@ -78,15 +79,33 @@ namespace AZ //! Creates a MaterialAsset from the MaterialSourceData content. //! @param assetId ID for the MaterialAsset - //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for resolving file-relative paths. + //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for + //! resolving file-relative paths. //! @param elevateWarnings Indicates whether to treat warnings as errors //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file Outcome> CreateMaterialAsset( Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", bool elevateWarnings = true, - bool includeMaterialPropertyNames = true - ) const; + bool includeMaterialPropertyNames = true) const; + + //! Creates a MaterialAsset from the MaterialSourceData content. + //! @param assetId ID for the MaterialAsset + //! @param materialSourceFilePath Indicates the path of the .material file that the MaterialSourceData represents. Used for + //! resolving file-relative paths. + //! @param elevateWarnings Indicates whether to treat warnings as errors + //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file + Outcome> CreateMaterialAssetFromSourceData( + Data::AssetId assetId, + AZStd::string_view materialSourceFilePath = "", + bool elevateWarnings = true, + bool includeMaterialPropertyNames = true) const; + + private: + static void ApplyMaterialSourceDataPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, + const AZStd::string_view& materialSourceFilePath, + const MaterialSourceData& materialSourceData); }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 1467b017d5..2a76befdf4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -126,7 +127,8 @@ namespace AZ return changesWereApplied ? ApplyVersionUpdatesResult::UpdatesApplied : ApplyVersionUpdatesResult::NoUpdates; } - Outcome > MaterialSourceData::CreateMaterialAsset(Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + Outcome> MaterialSourceData::CreateMaterialAsset( + Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const { MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); @@ -172,7 +174,95 @@ namespace AZ materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); } - for (auto& group : m_properties) + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + + Data::Asset material; + if (materialAssetCreator.End(material)) + { + return Success(material); + } + else + { + return Failure(); + } + } + + Outcome> MaterialSourceData::CreateMaterialAssetFromSourceData( + Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + { + MaterialAssetCreator materialAssetCreator; + materialAssetCreator.SetElevateWarnings(elevateWarnings); + + MaterialTypeSourceData materialTypeSourceData; + AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) + { + return Failure(); + } + + materialTypeSourceData.ResolveUvEnums(); + + auto materialTypeAsset = + materialTypeSourceData.CreateMaterialTypeAsset(AZ::Uuid::CreateRandom(), materialTypeSourcePath, elevateWarnings); + if (!materialTypeAsset.IsSuccess()) + { + return Failure(); + } + + materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + + AZStd::vector parentMaterialSourceDataVec; + + AZStd::string parentMaterialPath = m_parentMaterial; + AZStd::string parentMaterialSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentMaterialPath); + while (!parentMaterialPath.empty()) + { + MaterialSourceData parentMaterialSourceData; + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialSourcePath, parentMaterialSourceData)) + { + return Failure(); + } + + // Make sure the parent material has the same material type + auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); + auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentMaterialSourcePath, parentMaterialSourceData.m_materialType, 0); + if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || + materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) + { + AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); + return Failure(); + } + + parentMaterialPath = parentMaterialSourceData.m_parentMaterial; + parentMaterialSourcePath = AssetUtils::ResolvePathReference(parentMaterialSourcePath, parentMaterialPath); + parentMaterialSourceDataVec.push_back(parentMaterialSourceData); + } + + AZStd::reverse(parentMaterialSourceDataVec.begin(), parentMaterialSourceDataVec.end()); + for (const auto& parentMaterialSourceData : parentMaterialSourceDataVec) + { + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, parentMaterialSourceData); + } + + ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + + Data::Asset material; + if (materialAssetCreator.End(material)) + { + return Success(material); + } + else + { + return Failure(); + } + } + + void MaterialSourceData::ApplyMaterialSourceDataPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, + const AZStd::string_view& materialSourceFilePath, + const MaterialSourceData& materialSourceData) + { + for (auto& group : materialSourceData.m_properties) { for (auto& property : group.second) { @@ -183,43 +273,49 @@ namespace AZ } else { - MaterialPropertyIndex propertyIndex = materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); + MaterialPropertyIndex propertyIndex = + materialAssetCreator.m_materialPropertiesLayout->FindPropertyIndex(propertyId.GetFullName()); if (propertyIndex.IsValid()) { - const MaterialPropertyDescriptor* propertyDescriptor = materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); + const MaterialPropertyDescriptor* propertyDescriptor = + materialAssetCreator.m_materialPropertiesLayout->GetPropertyDescriptor(propertyIndex); switch (propertyDescriptor->GetDataType()) { case MaterialPropertyDataType::Image: - { - Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference(materialSourceFilePath, property.second.m_value.GetValue()); - - if (imageAssetResult.IsSuccess()) - { - auto& imageAsset = imageAssetResult.GetValue(); - // Load referenced images when load material - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); - } - else { - materialAssetCreator.ReportError("Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.second.m_value.GetValue().data()); + Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference( + materialSourceFilePath, property.second.m_value.GetValue()); + + if (imageAssetResult.IsSuccess()) + { + auto& imageAsset = imageAssetResult.GetValue(); + // Load referenced images when load material + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); + } + else + { + materialAssetCreator.ReportError( + "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), + property.second.m_value.GetValue().data()); + } } - } - break; + break; case MaterialPropertyDataType::Enum: - { - AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); - uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); - if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) { - materialAssetCreator.ReportError("Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); + AZ::Name enumName = AZ::Name(property.second.m_value.GetValue()); + uint32_t enumValue = propertyDescriptor->GetEnumValue(enumName); + if (enumValue == MaterialPropertyDescriptor::InvalidEnumValue) + { + materialAssetCreator.ReportError( + "Enum value '%s' couldn't be found in the 'enumValues' list", enumName.GetCStr()); + } + else + { + materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); + } } - else - { - materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), enumValue); - } - } - break; + break; default: materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), property.second.m_value); break; @@ -227,21 +323,12 @@ namespace AZ } else { - materialAssetCreator.ReportWarning("Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); + materialAssetCreator.ReportWarning( + "Can not find property id '%s' in MaterialPropertyLayout", propertyId.GetFullName().GetStringView().data()); } } } } - - Data::Asset material; - if (materialAssetCreator.End(material)) - { - return Success(material); - } - else - { - return Failure(); - } } } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index 46086dfecc..c81cf31d09 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -43,6 +43,7 @@ namespace AZ return false; } + m_asset->PostLoadInit(); m_asset->SetReady(); m_materialShaderResourceGroupLayout = nullptr; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 98af749261..1dcef43577 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -722,7 +722,7 @@ namespace MaterialEditor // we can create the asset dynamically from the source data. // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. - auto createResult = m_materialSourceData.CreateMaterialAsset(Uuid::CreateRandom(), m_absolutePath, true); + auto createResult = m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true); if (!createResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); From 30120b962607bba2698400d73b27036f3e5bfc63 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 22 Oct 2021 01:30:12 -0500 Subject: [PATCH 07/35] cleanup and setting asset preload flags Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 6 +-- .../RPI.Edit/Material/MaterialSourceData.cpp | 38 +++++++++---------- .../Material/MaterialTypeSourceData.cpp | 29 ++++++++------ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 739c4341a9..17dc4556fb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -102,10 +102,8 @@ namespace AZ bool includeMaterialPropertyNames = true) const; private: - static void ApplyMaterialSourceDataPropertiesToAssetCreator( - AZ::RPI::MaterialAssetCreator& materialAssetCreator, - const AZStd::string_view& materialSourceFilePath, - const MaterialSourceData& materialSourceData); + void ApplyPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const; }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 2a76befdf4..877e12ab2e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -174,7 +174,7 @@ namespace AZ materialAssetCreator.Begin(assetId, *parentMaterialAsset.GetValue().Get(), includeMaterialPropertyNames); } - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); Data::Asset material; if (materialAssetCreator.End(material)) @@ -211,21 +211,21 @@ namespace AZ materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); - AZStd::vector parentMaterialSourceDataVec; + AZStd::vector parentSourceDataStack; - AZStd::string parentMaterialPath = m_parentMaterial; - AZStd::string parentMaterialSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentMaterialPath); - while (!parentMaterialPath.empty()) + AZStd::string parentSourceRelPath = m_parentMaterial; + AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); + while (!parentSourceRelPath.empty()) { - MaterialSourceData parentMaterialSourceData; - if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialSourcePath, parentMaterialSourceData)) + MaterialSourceData parentSourceData; + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { return Failure(); } // Make sure the parent material has the same material type auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); - auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentMaterialSourcePath, parentMaterialSourceData.m_materialType, 0); + auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) { @@ -233,18 +233,18 @@ namespace AZ return Failure(); } - parentMaterialPath = parentMaterialSourceData.m_parentMaterial; - parentMaterialSourcePath = AssetUtils::ResolvePathReference(parentMaterialSourcePath, parentMaterialPath); - parentMaterialSourceDataVec.push_back(parentMaterialSourceData); + parentSourceDataStack.push_back(parentSourceData); + parentSourceRelPath = parentSourceData.m_parentMaterial; + parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); } - AZStd::reverse(parentMaterialSourceDataVec.begin(), parentMaterialSourceDataVec.end()); - for (const auto& parentMaterialSourceData : parentMaterialSourceDataVec) + while (!parentSourceDataStack.empty()) { - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, parentMaterialSourceData); + parentSourceDataStack.back().ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); + parentSourceDataStack.pop_back(); } - ApplyMaterialSourceDataPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath, *this); + ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); Data::Asset material; if (materialAssetCreator.End(material)) @@ -257,12 +257,10 @@ namespace AZ } } - void MaterialSourceData::ApplyMaterialSourceDataPropertiesToAssetCreator( - AZ::RPI::MaterialAssetCreator& materialAssetCreator, - const AZStd::string_view& materialSourceFilePath, - const MaterialSourceData& materialSourceData) + void MaterialSourceData::ApplyPropertiesToAssetCreator( + AZ::RPI::MaterialAssetCreator& materialAssetCreator, const AZStd::string_view& materialSourceFilePath) const { - for (auto& group : materialSourceData.m_properties) + for (auto& group : m_properties) { for (auto& property : group.second) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index 08f57c7cd3..b20873141b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -393,11 +393,14 @@ namespace AZ for (const ShaderVariantReferenceData& shaderRef : m_shaderCollection) { const auto& shaderFile = shaderRef.m_shaderFilePath; - const auto& shaderAsset = AssetUtils::LoadAsset(materialTypeSourceFilePath, shaderFile, 0); + auto shaderAssetResult = AssetUtils::LoadAsset(materialTypeSourceFilePath, shaderFile, 0); - if (shaderAsset) + if (shaderAssetResult) { - auto optionsLayout = shaderAsset.GetValue()->GetShaderOptionGroupLayout(); + auto shaderAsset = shaderAssetResult.GetValue(); + shaderAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + + auto optionsLayout = shaderAsset->GetShaderOptionGroupLayout(); ShaderOptionGroup options{ optionsLayout }; for (auto& iter : shaderRef.m_shaderOptionValues) { @@ -408,12 +411,11 @@ namespace AZ } materialTypeAssetCreator.AddShader( - shaderAsset.GetValue(), options.GetShaderVariantId(), - shaderRef.m_shaderTag.IsEmpty() ? Uuid::CreateRandom().ToString() : shaderRef.m_shaderTag - ); + shaderAsset, options.GetShaderVariantId(), + shaderRef.m_shaderTag.IsEmpty() ? Uuid::CreateRandom().ToString() : shaderRef.m_shaderTag); // Gather UV names - const ShaderInputContract& shaderInputContract = shaderAsset.GetValue()->GetInputContract(); + const ShaderInputContract& shaderInputContract = shaderAsset->GetInputContract(); for (const ShaderInputContract::StreamChannelInfo& channel : shaderInputContract.m_streamChannels) { const RHI::ShaderSemantic& semantic = channel.m_semantic; @@ -493,15 +495,20 @@ namespace AZ { case MaterialPropertyDataType::Image: { - Outcome> imageAssetResult = MaterialUtils::GetImageAssetReference(materialTypeSourceFilePath, property.m_value.GetValue()); + auto imageAssetResult = MaterialUtils::GetImageAssetReference( + materialTypeSourceFilePath, property.m_value.GetValue()); - if (imageAssetResult.IsSuccess()) + if (imageAssetResult) { - materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAssetResult.GetValue()); + auto imageAsset = imageAssetResult.GetValue(); + imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); + materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else { - materialTypeAssetCreator.ReportError("Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), property.m_value.GetValue().data()); + materialTypeAssetCreator.ReportError( + "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), + property.m_value.GetValue().data()); } } break; From 0724403f9014708c9e34fa7382cc4fcf10c82e76 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 25 Oct 2021 12:35:19 -0500 Subject: [PATCH 08/35] adding ifdef to compare loading vs creating material type assets Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 877e12ab2e..f1a41d0548 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -193,6 +193,7 @@ namespace AZ MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); +#if 0 MaterialTypeSourceData materialTypeSourceData; AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) @@ -208,6 +209,13 @@ namespace AZ { return Failure(); } +#else + auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); + if (!materialTypeAsset.IsSuccess()) + { + return Failure(); + } +#endif materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); From e632dc3b3982900770bd120cfa1238e1543489dd Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 26 Oct 2021 12:24:37 -0500 Subject: [PATCH 09/35] Moving material type asset PostInit call to be consistent with material asset Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp | 4 ++++ .../Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp index 76634201eb..48654d7769 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp @@ -188,6 +188,10 @@ namespace AZ void MaterialTypeAsset::SetReady() { m_status = AssetStatus::Ready; + + // If this was created dynamically using MaterialTypeAssetCreator (which is what calls SetReady()), + // we need to connect to the AssetBus for reloads. + PostLoadInit(); } bool MaterialTypeAsset::PostLoadInit() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp index c81cf31d09..46086dfecc 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAssetCreator.cpp @@ -43,7 +43,6 @@ namespace AZ return false; } - m_asset->PostLoadInit(); m_asset->SetReady(); m_materialShaderResourceGroupLayout = nullptr; From 48f3bb7d7a354c9b7340c69d7698e85fd9ada063 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 3 Nov 2021 23:56:59 -0700 Subject: [PATCH 10/35] Fixed missing initialization of ShaderCollection::Item::m_renderStatesOverlay. This RenderStates is used to override the values in the final draw packet, if the values are valid; it's supposed to be initialized to invalid values, but it wasn't. So the depth compare function was getting set to Less instead of GreaterEqual. This wasn't a problem when using serialized assets from disk, because the deserialization uses the default constructor which did initialize m_renderStatesOverlay. No all Item constructors initialize m_renderStatesOverlay. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> Signed-off-by: Guthrie Adams --- .../Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../Code/Source/RPI.Reflect/Material/ShaderCollection.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index f1a41d0548..7ff33b2d04 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -193,7 +193,7 @@ namespace AZ MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); -#if 0 +#if 1 MaterialTypeSourceData materialTypeSourceData; AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp index 87076891dd..16813cb6b7 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp @@ -126,8 +126,8 @@ namespace AZ } ShaderCollection::Item::Item() + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) { - m_renderStatesOverlay = RHI::GetInvalidRenderStates(); } ShaderCollection::Item& ShaderCollection::operator[](size_t i) @@ -156,7 +156,8 @@ namespace AZ } ShaderCollection::Item::Item(const Data::Asset& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId) - : m_shaderAsset(shaderAsset) + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) + , m_shaderAsset(shaderAsset) , m_shaderVariantId(variantId) , m_shaderTag(shaderTag) , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId) @@ -164,7 +165,8 @@ namespace AZ } ShaderCollection::Item::Item(Data::Asset&& shaderAsset, const AZ::Name& shaderTag, ShaderVariantId variantId) - : m_shaderAsset(AZStd::move(shaderAsset)) + : m_renderStatesOverlay(RHI::GetInvalidRenderStates()) + , m_shaderAsset(AZStd::move(shaderAsset)) , m_shaderVariantId(variantId) , m_shaderTag(shaderTag) , m_shaderOptionGroup(shaderAsset->GetShaderOptionGroupLayout(), variantId) From c0acbe7bd4cc17f1519efa9dee5a117c091d6be1 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 4 Nov 2021 12:27:18 -0500 Subject: [PATCH 11/35] =?UTF-8?q?Changed=20how=20asset=20creator=20generat?= =?UTF-8?q?es=20the=20asset=20instance.=20Instead=20of=20finding=20or=20cr?= =?UTF-8?q?eating=20the=20asset=20in=20the=20asset=20manager,=20one=20is?= =?UTF-8?q?=20directly=20instantiated=20and=20only=20added=20to=20the=20as?= =?UTF-8?q?set=20manager=20after=20creation=20is=20complete.=20This=20allo?= =?UTF-8?q?ws=20for=20reuse=20of=20previously=20loaded=20asset=20ids=20and?= =?UTF-8?q?=20will=20replace=20or=20=E2=80=9Creload=E2=80=9D=20a=20pre-exi?= =?UTF-8?q?sting=20asset=20with=20the=20newly=20created=20one.=20This=20al?= =?UTF-8?q?so=20sends=20although=20correct=20notifications.=20Changed=20ma?= =?UTF-8?q?terial=20document=20to=20load=20a=20source=20data=20are=20for?= =?UTF-8?q?=20the=20parent=20material=20as=20well.=20=20It=20was=20also=20?= =?UTF-8?q?a=20previously=20loading=20the=20parent=20material=20products?= =?UTF-8?q?=20asset=20which=20would=20be=20out=20of=20date=20compared=20to?= =?UTF-8?q?=20the=20source=20data.=20Changed=20material=20document=20to=20?= =?UTF-8?q?track=20source=20file=20dependency=20changes=20instead=20of=20p?= =?UTF-8?q?roduct=20asset=20changes.=20Fixed=20a=20bug=20or=20copy=20paste?= =?UTF-8?q?=20error=20in=20the=20document=20manager=20that=20was=20using?= =?UTF-8?q?=20the=20same=20container=20to=20track=20documents=20the=20modi?= =?UTF-8?q?fied=20externally=20and=20from=20other=20dependency=20changes.?= =?UTF-8?q?=20Returning=20source=20data=20dependencies=20when=20creating?= =?UTF-8?q?=20a=20material=20asset=20from=20source.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 3 +- .../Include/Atom/RPI.Reflect/AssetCreator.h | 3 +- .../RPI.Edit/Material/MaterialSourceData.cpp | 61 +++++++++++------- .../Material/MaterialTypeSourceData.cpp | 3 - .../AtomToolsDocumentSystemComponent.cpp | 14 +++-- .../AtomToolsDocumentSystemComponent.h | 4 +- .../Code/Source/Document/MaterialDocument.cpp | 63 ++++++++++--------- .../Code/Source/Document/MaterialDocument.h | 11 +--- 8 files changed, 86 insertions(+), 76 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 17dc4556fb..77bf45023d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -99,7 +99,8 @@ namespace AZ Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", bool elevateWarnings = true, - bool includeMaterialPropertyNames = true) const; + bool includeMaterialPropertyNames = true, + AZStd::unordered_set* sourceDependencies = nullptr) const; private: void ApplyPropertiesToAssetCreator( diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h index abdbe9cdce..79d43d0b8d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/AssetCreator.h @@ -118,7 +118,7 @@ namespace AZ ResetIssueCounts(); // Because the asset creator can be used multiple times - m_asset = Data::AssetManager::Instance().CreateAsset(assetId, AZ::Data::AssetLoadBehavior::PreLoad); + m_asset = Data::Asset(assetId, aznew AssetDataT, AZ::Data::AssetLoadBehavior::PreLoad); m_beginCalled = true; if (!m_asset) @@ -138,6 +138,7 @@ namespace AZ } else { + Data::AssetManager::Instance().AssignAssetData(m_asset); result = AZStd::move(m_asset); success = true; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 7ff33b2d04..c912826026 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -188,14 +188,20 @@ namespace AZ } Outcome> MaterialSourceData::CreateMaterialAssetFromSourceData( - Data::AssetId assetId, AZStd::string_view materialSourceFilePath, bool elevateWarnings, bool includeMaterialPropertyNames) const + Data::AssetId assetId, + AZStd::string_view materialSourceFilePath, + bool elevateWarnings, + bool includeMaterialPropertyNames, + AZStd::unordered_set* sourceDependencies) const { - MaterialAssetCreator materialAssetCreator; - materialAssetCreator.SetElevateWarnings(elevateWarnings); + const auto materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); + const auto materialTypeAssetId = AssetUtils::MakeAssetId(materialTypeSourcePath, 0); + if (!materialTypeAssetId.IsSuccess()) + { + return Failure(); + } -#if 1 MaterialTypeSourceData materialTypeSourceData; - AZStd::string materialTypeSourcePath = AssetUtils::ResolvePathReference(materialSourceFilePath, m_materialType); if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) { return Failure(); @@ -203,21 +209,16 @@ namespace AZ materialTypeSourceData.ResolveUvEnums(); - auto materialTypeAsset = - materialTypeSourceData.CreateMaterialTypeAsset(AZ::Uuid::CreateRandom(), materialTypeSourcePath, elevateWarnings); - if (!materialTypeAsset.IsSuccess()) - { - return Failure(); - } -#else - auto materialTypeAsset = AssetUtils::LoadAsset(materialSourceFilePath, m_materialType); + const auto materialTypeAsset = + materialTypeSourceData.CreateMaterialTypeAsset(materialTypeAssetId.GetValue(), materialTypeSourcePath, elevateWarnings); if (!materialTypeAsset.IsSuccess()) { return Failure(); } -#endif - materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + AZStd::unordered_set dependencies; + dependencies.insert(materialSourceFilePath); + dependencies.insert(materialTypeSourcePath); AZStd::vector parentSourceDataStack; @@ -225,6 +226,13 @@ namespace AZ AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); while (!parentSourceRelPath.empty()) { + if (dependencies.find(parentSourceAbsPath) != dependencies.end()) + { + return Failure(); + } + + dependencies.insert(parentSourceAbsPath); + MaterialSourceData parentSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { @@ -232,20 +240,22 @@ namespace AZ } // Make sure the parent material has the same material type - auto materialTypeIdOutcome1 = AssetUtils::MakeAssetId(materialSourceFilePath, m_materialType, 0); - auto materialTypeIdOutcome2 = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); - if (!materialTypeIdOutcome1.IsSuccess() || !materialTypeIdOutcome2.IsSuccess() || - materialTypeIdOutcome1.GetValue() != materialTypeIdOutcome2.GetValue()) + const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); + if (!parentTypeAssetId || parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } - parentSourceDataStack.push_back(parentSourceData); parentSourceRelPath = parentSourceData.m_parentMaterial; parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); + parentSourceDataStack.emplace_back(AZStd::move(parentSourceData)); } + MaterialAssetCreator materialAssetCreator; + materialAssetCreator.SetElevateWarnings(elevateWarnings); + materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); + while (!parentSourceDataStack.empty()) { parentSourceDataStack.back().ApplyPropertiesToAssetCreator(materialAssetCreator, materialSourceFilePath); @@ -257,12 +267,15 @@ namespace AZ Data::Asset material; if (materialAssetCreator.End(material)) { + if (sourceDependencies) + { + sourceDependencies->insert(dependencies.begin(), dependencies.end()); + } + return Success(material); } - else - { - return Failure(); - } + + return Failure(); } void MaterialSourceData::ApplyPropertiesToAssetCreator( diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp index b20873141b..396ba71e14 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialTypeSourceData.cpp @@ -398,8 +398,6 @@ namespace AZ if (shaderAssetResult) { auto shaderAsset = shaderAssetResult.GetValue(); - shaderAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); - auto optionsLayout = shaderAsset->GetShaderOptionGroupLayout(); ShaderOptionGroup options{ optionsLayout }; for (auto& iter : shaderRef.m_shaderOptionValues) @@ -501,7 +499,6 @@ namespace AZ if (imageAssetResult) { auto imageAsset = imageAssetResult.GetValue(); - imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad); materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); } else diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp index 5652e9fe23..00de2a7c4c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.cpp @@ -159,7 +159,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentExternallyModified(const AZ::Uuid& documentId) { - m_documentIdsToReopen.insert(documentId); + m_documentIdsWithExternalChanges.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -168,7 +168,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnDocumentDependencyModified(const AZ::Uuid& documentId) { - m_documentIdsToReopen.insert(documentId); + m_documentIdsWithDependencyChanges.insert(documentId); if (!AZ::TickBus::Handler::BusIsConnected()) { AZ::TickBus::Handler::BusConnect(); @@ -177,7 +177,7 @@ namespace AtomToolsFramework void AtomToolsDocumentSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { - for (const AZ::Uuid& documentId : m_documentIdsToReopen) + for (const AZ::Uuid& documentId : m_documentIdsWithExternalChanges) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -191,6 +191,8 @@ namespace AtomToolsFramework continue; } + m_documentIdsWithDependencyChanges.erase(documentId); + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; @@ -204,7 +206,7 @@ namespace AtomToolsFramework } } - for (const AZ::Uuid& documentId : m_documentIdsToReopen) + for (const AZ::Uuid& documentId : m_documentIdsWithDependencyChanges) { AZStd::string documentPath; AtomToolsDocumentRequestBus::EventResult(documentPath, documentId, &AtomToolsDocumentRequestBus::Events::GetAbsolutePath); @@ -231,8 +233,8 @@ namespace AtomToolsFramework } } - m_documentIdsToReopen.clear(); - m_documentIdsToReopen.clear(); + m_documentIdsWithDependencyChanges.clear(); + m_documentIdsWithExternalChanges.clear(); AZ::TickBus::Handler::BusDisconnect(); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h index 9c556a07e7..a0f5eb085d 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Document/AtomToolsDocumentSystemComponent.h @@ -85,8 +85,8 @@ namespace AtomToolsFramework AZStd::intrusive_ptr m_settings; AZStd::function m_documentCreator; AZStd::unordered_map> m_documentMap; - AZStd::unordered_set m_documentIdsToRebuild; - AZStd::unordered_set m_documentIdsToReopen; + AZStd::unordered_set m_documentIdsWithExternalChanges; + AZStd::unordered_set m_documentIdsWithDependencyChanges; const size_t m_maxMessageBoxLineCount = 15; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 1dcef43577..049d4c47ff 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -567,26 +567,26 @@ namespace MaterialEditor } } - void MaterialDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) + void MaterialDocument::SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, [[maybe_unused]] AZ::Uuid sourceUUID) { - if (m_sourceAssetId.m_guid == sourceUUID) + auto sourcePath = AZ::RPI::AssetUtils::ResolvePathReference(scanFolder, relativePath); + + if (m_absolutePath == sourcePath) { // ignore notifications caused by saving the open document if (!m_saveTriggeredInternally) { AZ_TracePrintf("MaterialDocument", "Material document changed externally: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentExternallyModified, m_id); } m_saveTriggeredInternally = false; } - } - - void MaterialDocument::OnAssetReloaded(AZ::Data::Asset asset) - { - if (m_dependentAssetIds.find(asset->GetId()) != m_dependentAssetIds.end()) + else if (m_sourceDependencies.find(sourcePath) != m_sourceDependencies.end()) { AZ_TracePrintf("MaterialDocument", "Material document dependency changed: '%s'.\n", m_absolutePath.c_str()); - AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); + AtomToolsFramework::AtomToolsDocumentNotificationBus::Broadcast( + &AtomToolsFramework::AtomToolsDocumentNotificationBus::Events::OnDocumentDependencyModified, m_id); } } @@ -655,7 +655,6 @@ namespace MaterialEditor return false; } - m_sourceAssetId = sourceAssetInfo.m_assetId; m_relativePath = sourceAssetInfo.m_relativePath; if (!AzFramework::StringFunc::Path::Normalize(m_relativePath)) { @@ -722,14 +721,15 @@ namespace MaterialEditor // we can create the asset dynamically from the source data. // Long term, the material document should not be concerned with assets at all. The viewport window should be the // only thing concerned with assets or instances. - auto createResult = m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true); - if (!createResult) + auto materialAssetResult = + m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true, true, &m_sourceDependencies); + if (!materialAssetResult) { AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); return false; } - m_materialAsset = createResult.GetValue(); + m_materialAsset = materialAssetResult.GetValue(); if (!m_materialAsset.IsReady()) { AZ_Error("MaterialDocument", false, "Material asset is not ready: '%s'.", m_absolutePath.c_str()); @@ -743,28 +743,35 @@ namespace MaterialEditor return false; } - // track material type asset to notify when dependencies change - m_dependentAssetIds.insert(materialTypeAsset->GetId()); - AZ::Data::AssetBus::MultiHandler::BusConnect(materialTypeAsset->GetId()); - AZStd::array_view parentPropertyValues = materialTypeAsset->GetDefaultPropertyValues(); AZ::Data::Asset parentMaterialAsset; if (!m_materialSourceData.m_parentMaterial.empty()) { - // There is a parent for this material - auto parentMaterialResult = AssetUtils::LoadAsset(m_absolutePath, m_materialSourceData.m_parentMaterial); - if (!parentMaterialResult) + AZ::RPI::MaterialSourceData parentMaterialSourceData; + const auto parentMaterialFilePath = AssetUtils::ResolvePathReference(m_absolutePath, m_materialSourceData.m_parentMaterial); + if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentMaterialFilePath, parentMaterialSourceData)) { - AZ_Error("MaterialDocument", false, "Parent material asset could not be loaded: '%s'.", m_materialSourceData.m_parentMaterial.c_str()); + AZ_Error("MaterialDocument", false, "Material parent source data could not be loaded for: '%s'.", parentMaterialFilePath.c_str()); return false; } - parentMaterialAsset = parentMaterialResult.GetValue(); - parentPropertyValues = parentMaterialAsset->GetPropertyValues(); + const auto parentMaterialAssetIdResult = AssetUtils::MakeAssetId(parentMaterialFilePath, 0); + if (!parentMaterialAssetIdResult) + { + AZ_Error("MaterialDocument", false, "Material parent asset ID could not be created: '%s'.", parentMaterialFilePath.c_str()); + return false; + } - // track parent material asset to notify when dependencies change - m_dependentAssetIds.insert(parentMaterialAsset->GetId()); - AZ::Data::AssetBus::MultiHandler::BusConnect(parentMaterialAsset->GetId()); + auto parentMaterialAssetResult = m_materialSourceData.CreateMaterialAssetFromSourceData( + parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true, &m_sourceDependencies); + if (!parentMaterialAssetResult) + { + AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); + return false; + } + + parentMaterialAsset = parentMaterialAssetResult.GetValue(); + parentPropertyValues = parentMaterialAsset->GetPropertyValues(); } // Creating a material from a material asset will fail if a texture is referenced but not loaded @@ -913,15 +920,13 @@ namespace MaterialEditor void MaterialDocument::Clear() { AZ::TickBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); AzToolsFramework::AssetSystemBus::Handler::BusDisconnect(); m_materialAsset = {}; m_materialInstance = {}; m_absolutePath.clear(); m_relativePath.clear(); - m_sourceAssetId = {}; - m_dependentAssetIds.clear(); + m_sourceDependencies.clear(); m_saveTriggeredInternally = {}; m_compilePending = {}; m_properties.clear(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h index 03997a2a91..452111f99a 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.h @@ -29,7 +29,6 @@ namespace MaterialEditor : public AtomToolsFramework::AtomToolsDocument , public MaterialDocumentRequestBus::Handler , private AZ::TickBus::Handler - , private AZ::Data::AssetBus::MultiHandler , private AzToolsFramework::AssetSystemBus::Handler { public: @@ -105,11 +104,6 @@ namespace MaterialEditor void SourceFileChanged(AZStd::string relativePath, AZStd::string scanFolder, AZ::Uuid sourceUUID) override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetBus::Router overrides... - void OnAssetReloaded(AZ::Data::Asset asset) override; - ////////////////////////////////////////////////////////////////////////// - bool SavePropertiesToSourceData(AZ::RPI::MaterialSourceData& sourceData, PropertyFilterFunction propertyFilter) const; bool OpenInternal(AZStd::string_view loadPath); @@ -137,11 +131,8 @@ namespace MaterialEditor // Material instance being edited AZ::Data::Instance m_materialInstance; - // Asset used to open document - AZ::Data::AssetId m_sourceAssetId; - // Set of assets that can trigger a document reload - AZStd::unordered_set m_dependentAssetIds; + AZStd::unordered_set m_sourceDependencies; // Track if document saved itself last to skip external modification notification bool m_saveTriggeredInternally = false; From 5afd701e2389d244c3ea03c529a806b20dd95993 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 4 Nov 2021 18:20:27 -0500 Subject: [PATCH 12/35] updated comments and error messages Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/MaterialSourceData.h | 1 + .../RPI.Edit/Material/MaterialSourceData.cpp | 25 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h index 77bf45023d..53d3072370 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h @@ -95,6 +95,7 @@ namespace AZ //! resolving file-relative paths. //! @param elevateWarnings Indicates whether to treat warnings as errors //! @param includeMaterialPropertyNames Indicates whether to save material property names into the material asset file + //! @param sourceDependencies if not null, will be populated with a set of all of the loaded material and material type paths Outcome> CreateMaterialAssetFromSourceData( Data::AssetId assetId, AZStd::string_view materialSourceFilePath = "", diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index c912826026..7c37d894d4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -198,12 +198,14 @@ namespace AZ const auto materialTypeAssetId = AssetUtils::MakeAssetId(materialTypeSourcePath, 0); if (!materialTypeAssetId.IsSuccess()) { + AZ_Error("MaterialSourceData", false, "Failed to create material type asset ID: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } MaterialTypeSourceData materialTypeSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(materialTypeSourcePath, materialTypeSourceData)) { + AZ_Error("MaterialSourceData", false, "Failed to load MaterialTypeSourceData: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } @@ -213,45 +215,58 @@ namespace AZ materialTypeSourceData.CreateMaterialTypeAsset(materialTypeAssetId.GetValue(), materialTypeSourcePath, elevateWarnings); if (!materialTypeAsset.IsSuccess()) { + AZ_Error("MaterialSourceData", false, "Failed to create material type asset from source data: '%s'.", materialTypeSourcePath.c_str()); return Failure(); } + // Track all of the material and material type assets loaded while trying to create a material asset from source data. This will + // be used for evaluating circular dependencies and returned for external monitoring or other use. AZStd::unordered_set dependencies; dependencies.insert(materialSourceFilePath); dependencies.insert(materialTypeSourcePath); + // Load and build a stack of MaterialSourceData from all of the parent materials in the hierarchy. Properties from the source + // data will be applied in reverse to the asset creator. AZStd::vector parentSourceDataStack; AZStd::string parentSourceRelPath = m_parentMaterial; AZStd::string parentSourceAbsPath = AssetUtils::ResolvePathReference(materialSourceFilePath, parentSourceRelPath); while (!parentSourceRelPath.empty()) { - if (dependencies.find(parentSourceAbsPath) != dependencies.end()) + if (!dependencies.insert(parentSourceAbsPath).second) { + AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath, parentSourceAbsPath.c_str()); return Failure(); } - dependencies.insert(parentSourceAbsPath); - MaterialSourceData parentSourceData; if (!AZ::RPI::JsonUtils::LoadObjectFromFile(parentSourceAbsPath, parentSourceData)) { + AZ_Error("MaterialSourceData", false, "Failed to load MaterialSourceData for parent material: '%s'.", parentSourceAbsPath.c_str()); return Failure(); } - // Make sure the parent material has the same material type + // Make sure that all materials in the hierarchy share the same material type const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); - if (!parentTypeAssetId || parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) + if (!parentTypeAssetId) + { + AZ_Error("MaterialSourceData", false, "Parent material asset ID isn't valid: '%s'.", parentSourceAbsPath.c_str()); + return Failure(); + } + + if (parentTypeAssetId.GetValue() != materialTypeAssetId.GetValue()) { AZ_Error("MaterialSourceData", false, "This material and its parent material do not share the same material type."); return Failure(); } + // Get the location of the next parent material and push the source data onto the stack parentSourceRelPath = parentSourceData.m_parentMaterial; parentSourceAbsPath = AssetUtils::ResolvePathReference(parentSourceAbsPath, parentSourceRelPath); parentSourceDataStack.emplace_back(AZStd::move(parentSourceData)); } + // Create the material asset from all the previously loaded source data MaterialAssetCreator materialAssetCreator; materialAssetCreator.SetElevateWarnings(elevateWarnings); materialAssetCreator.Begin(assetId, *materialTypeAsset.GetValue().Get(), includeMaterialPropertyNames); From 791d11c8f96cd500164688e5df225148167ead93 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Fri, 5 Nov 2021 22:06:31 -0500 Subject: [PATCH 13/35] Fix parent material loading Signed-off-by: Guthrie Adams --- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- .../MaterialEditor/Code/Source/Document/MaterialDocument.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index 7c37d894d4..e5466a173f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -235,7 +235,7 @@ namespace AZ { if (!dependencies.insert(parentSourceAbsPath).second) { - AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath, parentSourceAbsPath.c_str()); + AZ_Error("MaterialSourceData", false, "Detected circular dependency between materials: '%s' and '%s'.", materialSourceFilePath.data(), parentSourceAbsPath.c_str()); return Failure(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 049d4c47ff..ee58cbea3e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -762,8 +762,8 @@ namespace MaterialEditor return false; } - auto parentMaterialAssetResult = m_materialSourceData.CreateMaterialAssetFromSourceData( - parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true, &m_sourceDependencies); + auto parentMaterialAssetResult = parentMaterialSourceData.CreateMaterialAssetFromSourceData( + parentMaterialAssetIdResult.GetValue(), parentMaterialFilePath, true, true); if (!parentMaterialAssetResult) { AZ_Error("MaterialDocument", false, "Material parent asset could not be created from source data: '%s'.", parentMaterialFilePath.c_str()); From c372761f4e348bf63f7f7b6b0ee930f177bfd2da Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 7 Nov 2021 15:04:46 -0600 Subject: [PATCH 14/35] Changing lua material functor script loading code to pass the correct sub ID for a compiled script asset Signed-off-by: Guthrie Adams --- .../Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp index b230953f8c..37bd5a19f2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp @@ -137,7 +137,7 @@ namespace AZ } else if (!m_luaSourceFile.empty()) { - auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile); + auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); if (!loadOutcome) { AZ_Error("LuaMaterialFunctorSourceData", false, "Could not load script file '%s'", m_luaSourceFile.c_str()); From dcb3ac43375b15b1fde049e8c8b9d6a3907883cd Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Mon, 8 Nov 2021 17:53:03 -0700 Subject: [PATCH 15/35] Set skybox exposure during ReflectionProbe bake Signed-off-by: dmcdiar --- .../Source/ReflectionProbe/ReflectionProbe.cpp | 15 +++++++++------ .../Code/Source/ReflectionProbe/ReflectionProbe.h | 6 ++++-- .../EditorReflectionProbeComponent.cpp | 4 ++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index c4ea3249d5..4ac5782b04 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -120,15 +120,17 @@ namespace AZ m_scene->RemoveRenderPipeline(m_environmentCubeMapPipelineId); m_environmentCubeMapPass = nullptr; - // restore exposure - sceneSrg->SetConstant(m_iblExposureConstantIndex, m_previousExposure); + // restore exposures + sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_previousGlobalIblExposure); + sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_previousSkyBoxExposure); m_buildingCubeMap = false; } else { - // set exposure to the user specified value while baking the cubemap - sceneSrg->SetConstant(m_iblExposureConstantIndex, m_bakeExposure); + // set exposures to the user specified value while baking the cubemap + sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_bakeExposure); + sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_bakeExposure); } } @@ -305,9 +307,10 @@ namespace AZ const RPI::Ptr& rootPass = environmentCubeMapPipeline->GetRootPass(); rootPass->AddChild(m_environmentCubeMapPass); - // store the current IBL exposure value + // store the current IBL exposure values Data::Instance sceneSrg = m_scene->GetShaderResourceGroup(); - m_previousExposure = sceneSrg->GetConstant(m_iblExposureConstantIndex); + m_previousGlobalIblExposure = sceneSrg->GetConstant(m_globalIblExposureConstantIndex); + m_previousSkyBoxExposure = sceneSrg->GetConstant(m_skyBoxExposureConstantIndex); m_scene->AddRenderPipeline(environmentCubeMapPipeline); } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 485f380463..17ef54367b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -180,8 +180,10 @@ namespace AZ RPI::Ptr m_environmentCubeMapPass = nullptr; RPI::RenderPipelineId m_environmentCubeMapPipelineId; BuildCubeMapCallback m_callback; - RHI::ShaderInputNameIndex m_iblExposureConstantIndex = "m_iblExposure"; - float m_previousExposure = 0.0f; + RHI::ShaderInputNameIndex m_globalIblExposureConstantIndex = "m_iblExposure"; + RHI::ShaderInputNameIndex m_skyBoxExposureConstantIndex = "m_cubemapExposure"; + float m_previousGlobalIblExposure = 0.0f; + float m_previousSkyBoxExposure = 0.0f; bool m_buildingCubeMap = false; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index c7179587c0..578c6e9300 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -64,8 +64,8 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::BakeReflectionProbe) ->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting) ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorReflectionProbeComponent::m_bakeExposure, "Bake Exposure", "Exposure to use when baking the cubemap") - ->Attribute(AZ::Edit::Attributes::SoftMin, -5.0f) - ->Attribute(AZ::Edit::Attributes::SoftMax, 5.0f) + ->Attribute(AZ::Edit::Attributes::SoftMin, -16.0f) + ->Attribute(AZ::Edit::Attributes::SoftMax, 16.0f) ->Attribute(AZ::Edit::Attributes::Min, -20.0f) ->Attribute(AZ::Edit::Attributes::Max, 20.0f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnBakeExposureChanged) From c5cb90ddb79d94df5b663aec27311a70c9925209 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 8 Nov 2021 20:24:53 -0800 Subject: [PATCH 16/35] Merge pull request #4426 from aws-lumberyard-dev/Atom/santorac/FixSceneSrgTime Fixed potential render scene time precision issues. The timestamp was simply converted from GetTimeAtCurrentTick to a float. Since this value is backed by QueryPerformanceCounter which is 0 at boot, you could see broken animations on the GPU when your system has been on for a long time. So I simplified the RPI's time API (removed unused code), and subtracted the application start time each frame before converting the time value to a float. Also moved FindShaderInputConstantIndex("m_time") to be called only once, instead of every frame. Testing: Originally: I had a local material shader that did vertex animation and it wasn't working at all before, and now it works. More recently, I made local changes to StandardPBR to add a simple sin wave animation. I also modified GetTimeNowMicroSecond() to artificially add 30 days to the clock. This showed choppy animation before my changes, and smooth animation after. AtomSampleViewer passed dx12 and vulkan (other than pre-existing issues) Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Code/Include/Atom/RPI.Public/RPISystem.h | 6 +++--- .../Include/Atom/RPI.Public/RenderPipeline.h | 3 +-- .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 15 +++++--------- .../RPI/Code/Source/RPI.Public/RPISystem.cpp | 20 ++++++++++--------- .../Code/Source/RPI.Public/RenderPipeline.cpp | 2 +- .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 17 ++++++++-------- 6 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h index 92370c5a82..9138c0b418 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h @@ -97,8 +97,7 @@ namespace AZ // SystemTickBus::OnTick void OnSystemTick() override; - // Fill system time and game time information for simulation or rendering - void FillTickTimeInfo(); + float GetCurrentTime(); // The set of core asset handlers registered by the system. AZStd::vector> m_assetHandlers; @@ -124,7 +123,8 @@ namespace AZ // The job policy used for feature processor's rendering prepare RHI::JobPolicy m_prepareRenderJobPolicy = RHI::JobPolicy::Parallel; - TickTimeInfo m_tickTime; + ScriptTimePoint m_startTime; + float m_currentSimulationTime = 0.0f; RPISystemDescriptor m_descriptor; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h index fcf812cc38..6cba0c774f 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -32,7 +32,6 @@ namespace AZ namespace RPI { class Scene; - struct TickTimeInfo; class ShaderResourceGroup; class AnyAsset; class WindowContext; @@ -203,7 +202,7 @@ namespace AZ void OnRemovedFromScene(Scene* scene); // Called when this pipeline is about to be rendered - void OnStartFrame(const TickTimeInfo& tick); + void OnStartFrame(float time); // Called when the rendering of current frame is finished. void OnFrameEnd(); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h index f86383101a..1411a8d996 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -48,14 +48,6 @@ namespace AZ // Callback function to modify values of a ShaderResourceGroup using ShaderResourceGroupCallback = AZStd::function; - //! A structure for ticks which contains system time and game time. - struct TickTimeInfo - { - float m_currentGameTime; - float m_gameDeltaTime = 0; - }; - - class Scene final : public SceneRequestBus::Handler { @@ -179,12 +171,14 @@ namespace AZ // Cpu simulation which runs all active FeatureProcessor Simulate() functions. // @param jobPolicy if it's JobPolicy::Parallel, the function will spawn a job thread for each FeatureProcessor's simulation. - void Simulate(const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy); + // @param simulationTime the number of seconds since the application started + void Simulate(RHI::JobPolicy jobPolicy, float simulationTime); // Collect DrawPackets from FeatureProcessors // @param jobPolicy if it's JobPolicy::Parallel, the function will spawn a job thread for each FeatureProcessor's // PrepareRender. - void PrepareRender(const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy); + // @param simulationTime the number of seconds since the application started; this is the same time value that was passed to Simulate() + void PrepareRender(RHI::JobPolicy jobPolicy, float simulationTime); // Function called when the current frame is finished rendering. void OnFrameEnd(); @@ -267,6 +261,7 @@ namespace AZ // Registry which allocates draw filter tag for RenderPipeline RHI::Ptr m_drawFilterTagRegistry; + RHI::ShaderInputConstantIndex m_timeInputIndex; float m_simulationTime; }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index 943966c13b..2b32503838 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -268,21 +268,23 @@ namespace AZ AssetInitBus::Broadcast(&AssetInitBus::Events::PostLoadInit); - // Update tick time info - FillTickTimeInfo(); + m_currentSimulationTime = GetCurrentTime(); for (auto& scene : m_scenes) { - scene->Simulate(m_tickTime, m_simulationJobPolicy); + scene->Simulate(m_simulationJobPolicy, m_currentSimulationTime); } } - void RPISystem::FillTickTimeInfo() + float RPISystem::GetCurrentTime() { - AZ::TickRequestBus::BroadcastResult(m_tickTime.m_gameDeltaTime, &AZ::TickRequestBus::Events::GetTickDeltaTime); - ScriptTimePoint currentTime; - AZ::TickRequestBus::BroadcastResult(currentTime, &AZ::TickRequestBus::Events::GetTimeAtCurrentTick); - m_tickTime.m_currentGameTime = static_cast(currentTime.GetSeconds()); + ScriptTimePoint timeAtCurrentTick; + AZ::TickRequestBus::BroadcastResult(timeAtCurrentTick, &AZ::TickRequestBus::Events::GetTimeAtCurrentTick); + + // We subtract the start time to maximize precision of the time value, since we will be converting it to a float. + double currentTime = timeAtCurrentTick.GetSeconds() - m_startTime.GetSeconds(); + + return aznumeric_cast(currentTime); } void RPISystem::RenderTick() @@ -301,7 +303,7 @@ namespace AZ // [GFX TODO] We may parallel scenes' prepare render. for (auto& scenePtr : m_scenes) { - scenePtr->PrepareRender(m_tickTime, m_prepareRenderJobPolicy); + scenePtr->PrepareRender(m_prepareRenderJobPolicy, m_currentSimulationTime); } m_rhiSystem.FrameUpdate( diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp index 6378a249a4..8d4303f187 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp @@ -375,7 +375,7 @@ namespace AZ m_scene->RemoveRenderPipeline(m_nameId); } - void RenderPipeline::OnStartFrame([[maybe_unused]] const TickTimeInfo& tick) + void RenderPipeline::OnStartFrame([[maybe_unused]] float time) { AZ_PROFILE_SCOPE(RPI, "RenderPipeline: OnStartFrame"); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 41fefda656..b27e3518e1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -44,6 +44,9 @@ namespace AZ { auto shaderAsset = RPISystemInterface::Get()->GetCommonShaderAssetForSrgs(); scene->m_srg = ShaderResourceGroup::Create(shaderAsset, sceneSrgLayout->GetName()); + + // Set value for constants defined in SceneTimeSrg.azsli + scene->m_timeInputIndex = scene->m_srg->FindShaderInputConstantIndex(Name{ "m_time" }); } scene->m_name = sceneDescriptor.m_nameId; @@ -410,11 +413,11 @@ namespace AZ //[GFX TODO]: the completion job should start here } - void Scene::Simulate([[maybe_unused]] const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) + void Scene::Simulate(RHI::JobPolicy jobPolicy, float simulationTime) { AZ_PROFILE_SCOPE(RPI, "Scene: Simulate"); - m_simulationTime = tickInfo.m_currentGameTime; + m_simulationTime = simulationTime; // If previous simulation job wasn't done, wait for it to finish. if (m_taskGraphActive) @@ -483,11 +486,9 @@ namespace AZ { if (m_srg) { - // Set value for constants defined in SceneTimeSrg.azsli - RHI::ShaderInputConstantIndex timeIndex = m_srg->FindShaderInputConstantIndex(Name{ "m_time" }); - if (timeIndex.IsValid()) + if (m_timeInputIndex.IsValid()) { - m_srg->SetConstant(timeIndex, m_simulationTime); + m_srg->SetConstant(m_timeInputIndex, m_simulationTime); } // signal any handlers to update values for their partial scene srg @@ -620,7 +621,7 @@ namespace AZ WaitAndCleanCompletionJob(finalizeDrawListsCompletion); } - void Scene::PrepareRender(const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) + void Scene::PrepareRender(RHI::JobPolicy jobPolicy, float simulationTime) { AZ_PROFILE_SCOPE(RPI, "Scene: PrepareRender"); @@ -644,7 +645,7 @@ namespace AZ if (pipeline->NeedsRender()) { activePipelines.push_back(pipeline); - pipeline->OnStartFrame(tickInfo); + pipeline->OnStartFrame(simulationTime); } } } From af08cc5ab319c7275d367f6af9305d3107276099 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Tue, 9 Nov 2021 10:05:33 +0000 Subject: [PATCH 17/35] Various bug fixes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../TerrainSurfaceMaterialsListComponent.cpp | 13 +++++++++---- .../TerrainSurfaceMaterialsListComponent.h | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp index 271919070c..7da6130f7b 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp @@ -74,7 +74,7 @@ namespace Terrain ->DataElement( AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials, - "Gradient to Material Mappings", "Maps surfaces to materials."); + "Material Mappings", "Maps surfaces to materials."); } } } @@ -112,6 +112,11 @@ namespace Terrain { } + TerrainSurfaceMaterialsListComponent ::~TerrainSurfaceMaterialsListComponent() + { + Deactivate(); + } + void TerrainSurfaceMaterialsListComponent::Activate() { m_cachedAabb = AZ::Aabb::CreateNull(); @@ -123,7 +128,7 @@ namespace Terrain { surfaceMaterialMapping.m_active = false; surfaceMaterialMapping.m_materialAsset.QueueLoad(); - AZ::Data::AssetBus::Handler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId()); + AZ::Data::AssetBus::MultiHandler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId()); } } } @@ -136,7 +141,7 @@ namespace Terrain { if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid()) { - AZ::Data::AssetBus::Handler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId()); + AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId()); surfaceMaterialMapping.m_materialAsset.Release(); surfaceMaterialMapping.m_materialInstance.reset(); surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); @@ -202,7 +207,7 @@ namespace Terrain // Don't disconnect from the AssetBus if this material is mapped more than once. if (CountMaterialIDInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1) { - AZ::Data::AssetBus::Handler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId); + AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId); } surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h index 7c36033c41..a6650bf035 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h @@ -53,7 +53,7 @@ namespace Terrain class TerrainSurfaceMaterialsListComponent : public AZ::Component , private TerrainAreaMaterialRequestBus::Handler - , private AZ::Data::AssetBus::Handler + , private AZ::Data::AssetBus::MultiHandler , private LmbrCentral::ShapeComponentNotificationsBus::Handler { public: @@ -67,7 +67,7 @@ namespace Terrain TerrainSurfaceMaterialsListComponent(const TerrainSurfaceMaterialsListConfig& configuration); TerrainSurfaceMaterialsListComponent() = default; - ~TerrainSurfaceMaterialsListComponent() = default; + ~TerrainSurfaceMaterialsListComponent(); ////////////////////////////////////////////////////////////////////////// // AZ::Component interface implementation From bff8a2e147f66403b19f9658d556c5be9c6aaedc Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Tue, 9 Nov 2021 16:00:26 +0000 Subject: [PATCH 18/35] improved fix Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- .../Components/TerrainSurfaceMaterialsListComponent.cpp | 7 +------ .../Components/TerrainSurfaceMaterialsListComponent.h | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp index 7da6130f7b..1dbcbd1120 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp @@ -112,11 +112,6 @@ namespace Terrain { } - TerrainSurfaceMaterialsListComponent ::~TerrainSurfaceMaterialsListComponent() - { - Deactivate(); - } - void TerrainSurfaceMaterialsListComponent::Activate() { m_cachedAabb = AZ::Aabb::CreateNull(); @@ -243,7 +238,7 @@ namespace Terrain // All materials have been deactivated, stop listening for requests and notifications. m_cachedAabb = AZ::Aabb::CreateNull(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); - TerrainAreaMaterialRequestBus::Handler::BusConnect(GetEntityId()); + TerrainAreaMaterialRequestBus::Handler::BusDisconnect(); } } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h index a6650bf035..72eee5f68e 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h @@ -67,7 +67,7 @@ namespace Terrain TerrainSurfaceMaterialsListComponent(const TerrainSurfaceMaterialsListConfig& configuration); TerrainSurfaceMaterialsListComponent() = default; - ~TerrainSurfaceMaterialsListComponent(); + ~TerrainSurfaceMaterialsListComponent() = default; ////////////////////////////////////////////////////////////////////////// // AZ::Component interface implementation From c182b213ad8a4f965fd2f6e786b05103b0ce4204 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Tue, 9 Nov 2021 10:02:11 -0800 Subject: [PATCH 19/35] Remove timeout in the mount step We no longer need a timeout here. A timeout mechanism was added to the mount script to raise an exeception if the EBS volume is not mounted in the configured timeframe. This also causes a bug with the retry mechanism where Jenkins will hit this timeout in the event the node goes offline during the setup stage instead of raising an exception. Signed-off-by: brianherrera --- scripts/build/Jenkins/Jenkinsfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 1388366661..34732a5fad 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -277,9 +277,7 @@ def HandleDriveMount(String snapshot, String repositoryName, String projectName, if(recreateVolume) { palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action delete --repository_name ${repositoryName} --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Deleting volume', winSlashReplacement=false) } - timeout(5) { - palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action mount --snapshot ${snapshot} --repository_name ${repositoryName} --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Mounting volume', winSlashReplacement=false) - } + palSh("${pythonCmd} ${INCREMENTAL_BUILD_SCRIPT_PATH} --action mount --snapshot ${snapshot} --repository_name ${repositoryName} --project ${projectName} --pipeline ${pipeline} --branch ${branchName} --platform ${platform} --build_type ${buildType}", 'Mounting volume', winSlashReplacement=false) if(env.IS_UNIX) { sh label: 'Setting volume\'s ownership', From eb60dd404b4ba9286981bc24d901ee4cfbc80786 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Tue, 9 Nov 2021 12:17:58 -0700 Subject: [PATCH 20/35] Moved probe exposure to specular only, since it's not used by the diffuse Signed-off-by: dmcdiar --- .../Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index 31439de144..3254b8e4ed 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -85,12 +85,12 @@ void ApplyIBL(Surface surface, inout LightingData lightingData) if(useIbl) { - float exposure = pow(2.0, ObjectSrg::m_reflectionProbeData.m_exposure); + float globalIblExposure = pow(2.0, SceneSrg::m_iblExposure); if(useDiffuseIbl) { float3 iblDiffuse = GetIblDiffuse(surface.normal, surface.albedo, lightingData.diffuseResponse); - lightingData.diffuseLighting += (iblDiffuse * exposure * lightingData.diffuseAmbientOcclusion); + lightingData.diffuseLighting += (iblDiffuse * globalIblExposure * lightingData.diffuseAmbientOcclusion); } if(useSpecularIbl) @@ -116,6 +116,7 @@ void ApplyIBL(Surface surface, inout LightingData lightingData) iblSpecular = iblSpecular * (1.0 - clearCoatResponse) * (1.0 - clearCoatResponse) + clearCoatIblSpecular; } + float exposure = ObjectSrg::m_reflectionProbeData.m_useReflectionProbe ? pow(2.0, ObjectSrg::m_reflectionProbeData.m_exposure) : globalIblExposure; lightingData.specularLighting += (iblSpecular * exposure); } } From e3b1c4b7d09b63bea6503c66f9686b6f9fa4556e Mon Sep 17 00:00:00 2001 From: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> Date: Tue, 9 Nov 2021 11:27:32 -0800 Subject: [PATCH 21/35] Move swapchain and image recreation to the end of the frame (#5388) Signed-off-by: jiaweig --- .../RHI/Code/Include/Atom/RHI/SwapChain.h | 11 ++ .../RHI/FrameGraphAttachmentDatabase.cpp | 8 +- Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp | 145 ++++++++---------- .../RHI/Vulkan/Code/Source/RHI/SwapChain.cpp | 22 ++- .../RHI/Vulkan/Code/Source/RHI/SwapChain.h | 1 + 5 files changed, 101 insertions(+), 86 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h index 97ac3baa90..abad1fb263 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h @@ -75,6 +75,9 @@ namespace AZ //! Return True if the swap chain prefers exclusive full screen mode and a transition happened, false otherwise. virtual bool SetExclusiveFullScreenState([[maybe_unused]]bool fullScreenState) { return false; } + //! Recreate the swapchain if it becomes invalid during presenting. This should happen at the end of the frame + //! due to images being used as attachments in the frame graph. + virtual void ProcessRecreation() {}; protected: SwapChain(); @@ -98,6 +101,14 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// + //! Shutdown and clear all the images. + void ShutdownImages(); + + //! Initialized all the images. + ResultCode InitImages(); + + //! Flag indicating if swapchain recreation is needed at the end of the frame. + bool m_pendingRecreation = false; private: bool ValidateDescriptor(const SwapChainDescriptor& descriptor) const; diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp index 6bac2b8c7d..388277ff59 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphAttachmentDatabase.cpp @@ -134,7 +134,6 @@ namespace AZ m_scopeAttachmentLookup.clear(); m_imageAttachments.clear(); m_bufferAttachments.clear(); - m_swapChainAttachments.clear(); m_importedImageAttachments.clear(); m_importedBufferAttachments.clear(); m_transientImageAttachments.clear(); @@ -153,6 +152,13 @@ namespace AZ delete attachment; } m_attachments.clear(); + + for (auto swapchainAttachment : m_swapChainAttachments) + { + swapchainAttachment->GetSwapChain()->ProcessRecreation(); + } + + m_swapChainAttachments.clear(); } ImageDescriptor FrameGraphAttachmentDatabase::GetImageDescriptor(const AttachmentId& attachmentId) const diff --git a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp index ff1f0e69a6..074eedf1b6 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp @@ -58,43 +58,68 @@ namespace AZ // Overwrite descriptor dimensions with the native ones (the ones assigned by the platform) returned by InitInternal. m_descriptor.m_dimensions = nativeDimensions; - m_images.reserve(m_descriptor.m_dimensions.m_imageCount); + resultCode = InitImages(); + } - for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx) - { - m_images.emplace_back(RHI::Factory::Get().CreateImage()); - } + return resultCode; + } - InitImageRequest request; + void SwapChain::ShutdownImages() + { + // Shutdown existing set of images. + uint32_t imageSize = aznumeric_cast(m_images.size()); + for (uint32_t imageIdx = 0; imageIdx < imageSize; ++imageIdx) + { + m_images[imageIdx]->Shutdown(); + } - RHI::ImageDescriptor& imageDescriptor = request.m_descriptor; - imageDescriptor.m_dimension = RHI::ImageDimension::Image2D; - imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color; - imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth; - imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight; - imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat; + m_images.clear(); + } - for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx) - { - request.m_image = m_images[imageIdx].get(); - request.m_imageIndex = imageIdx; + ResultCode SwapChain::InitImages() + { + ResultCode resultCode = ResultCode::Success; + + m_images.reserve(m_descriptor.m_dimensions.m_imageCount); + + // If the new display mode has more buffers, add them. + for (uint32_t i = 0; i < m_descriptor.m_dimensions.m_imageCount; ++i) + { + m_images.emplace_back(RHI::Factory::Get().CreateImage()); + } + + InitImageRequest request; + + RHI::ImageDescriptor& imageDescriptor = request.m_descriptor; + imageDescriptor.m_dimension = RHI::ImageDimension::Image2D; + imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color; + imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth; + imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight; + imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat; - resultCode = ImagePoolBase::InitImage( - request.m_image, - imageDescriptor, - [this, &request]() + for (uint32_t imageIdx = 0; imageIdx < m_descriptor.m_dimensions.m_imageCount; ++imageIdx) + { + request.m_image = m_images[imageIdx].get(); + request.m_imageIndex = imageIdx; + + resultCode = ImagePoolBase::InitImage( + request.m_image, imageDescriptor, + [this, &request]() { return InitImageInternal(request); }); - if (resultCode != ResultCode::Success) - { - Shutdown(); - break; - } + if (resultCode != ResultCode::Success) + { + AZ_Error("Swapchain", false, "Failed to initialize images."); + Shutdown(); + break; } } + // Reset the current index back to 0 so we match the platform swap chain. + m_currentImageIndex = 0; + return resultCode; } @@ -105,63 +130,15 @@ namespace AZ } ResultCode SwapChain::Resize(const RHI::SwapChainDimensions& dimensions) - { - // Shutdown existing set of images. - for (uint32_t imageIdx = 0; imageIdx < GetImageCount(); ++imageIdx) - { - m_images[imageIdx]->Shutdown(); - } + { + ShutdownImages(); SwapChainDimensions nativeDimensions = dimensions; ResultCode resultCode = ResizeInternal(dimensions, &nativeDimensions); if (resultCode == ResultCode::Success) { m_descriptor.m_dimensions = nativeDimensions; - m_images.reserve(m_descriptor.m_dimensions.m_imageCount); - - // If the new display mode has more buffers, add them. - while (m_images.size() < static_cast(m_descriptor.m_dimensions.m_imageCount)) - { - m_images.emplace_back(RHI::Factory::Get().CreateImage()); - } - - // If it has fewer, trim down. - while (m_images.size() > static_cast(m_descriptor.m_dimensions.m_imageCount)) - { - m_images.pop_back(); - } - - InitImageRequest request; - - RHI::ImageDescriptor& imageDescriptor = request.m_descriptor; - imageDescriptor.m_dimension = RHI::ImageDimension::Image2D; - imageDescriptor.m_bindFlags = RHI::ImageBindFlags::Color; - imageDescriptor.m_size.m_width = m_descriptor.m_dimensions.m_imageWidth; - imageDescriptor.m_size.m_height = m_descriptor.m_dimensions.m_imageHeight; - imageDescriptor.m_format = m_descriptor.m_dimensions.m_imageFormat; - - for (uint32_t imageIdx = 0; imageIdx < GetImageCount(); ++imageIdx) - { - request.m_image = m_images[imageIdx].get(); - request.m_imageIndex = imageIdx; - - resultCode = ImagePoolBase::InitImage( - request.m_image, - imageDescriptor, - [this, &request]() - { - return InitImageInternal(request); - }); - - if (resultCode != ResultCode::Success) - { - Shutdown(); - break; - } - } - - // Reset the current index back to 0 so we match the platform swap chain. - m_currentImageIndex = 0; + resultCode = InitImages(); } return resultCode; @@ -188,7 +165,7 @@ namespace AZ uint32_t SwapChain::GetImageCount() const { - return static_cast(m_images.size()); + return aznumeric_cast(m_images.size()); } uint32_t SwapChain::GetCurrentImageIndex() const @@ -209,8 +186,18 @@ namespace AZ void SwapChain::Present() { AZ_TRACE_METHOD(); - m_currentImageIndex = PresentInternal(); - AZ_Assert(m_currentImageIndex < m_images.size(), "Invalid image index"); + // Due to swapchain recreation, the images are refreshed. + // There is no need to present swapchain for this frame. + const uint32_t imageCount = aznumeric_cast(m_images.size()); + if (imageCount == 0) + { + return; + } + else + { + m_currentImageIndex = PresentInternal(); + AZ_Assert(m_currentImageIndex < imageCount, "Invalid image index"); + } } } } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp index bef2b154e1..19c88ec34f 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp @@ -59,6 +59,19 @@ namespace AZ m_swapChainBarrier.m_isValid = true; } + void SwapChain::ProcessRecreation() + { + if (m_pendingRecreation) + { + ShutdownImages(); + InvalidateNativeSwapChain(); + CreateSwapchain(); + InitImages(); + + m_pendingRecreation = false; + } + } + void SwapChain::SetVerticalSyncIntervalInternal(uint32_t previousVsyncInterval) { if (GetDescriptor().m_verticalSyncInterval == 0 || previousVsyncInterval == 0) @@ -231,8 +244,7 @@ namespace AZ // VK_SUBOPTIMAL_KHR is treated as success, but we better update the surface info as well. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { - InvalidateNativeSwapChain(); - CreateSwapchain(); + m_pendingRecreation = true; } else { @@ -246,18 +258,16 @@ namespace AZ } }; - m_presentationQueue->QueueCommand(AZStd::move(presentCommand)); - uint32_t acquiredImageIndex = GetCurrentImageIndex(); RHI::ResultCode result = AcquireNewImage(&acquiredImageIndex); if (result == RHI::ResultCode::Fail) { - InvalidateNativeSwapChain(); - CreateSwapchain(); + m_pendingRecreation = true; return 0; } else { + m_presentationQueue->QueueCommand(AZStd::move(presentCommand)); return acquiredImageIndex; } } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h index ee2ff3c207..68abc97b2d 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.h @@ -51,6 +51,7 @@ namespace AZ void QueueBarrier(const VkPipelineStageFlags src, const VkPipelineStageFlags dst, const VkImageMemoryBarrier& imageBarrier); + void ProcessRecreation() override; private: SwapChain() = default; From 7cc9c584b78a1c66e714a95d046a1123849f4f10 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 9 Nov 2021 13:53:04 -0600 Subject: [PATCH 22/35] Ensure QtForPython is a proper dependency for the PythonToolGem. Signed-off-by: Chris Galvan --- Templates/PythonToolGem/Template/Code/CMakeLists.txt | 2 ++ Templates/PythonToolGem/Template/gem.json | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Templates/PythonToolGem/Template/Code/CMakeLists.txt b/Templates/PythonToolGem/Template/Code/CMakeLists.txt index a6044e717b..b90f2d7703 100644 --- a/Templates/PythonToolGem/Template/Code/CMakeLists.txt +++ b/Templates/PythonToolGem/Template/Code/CMakeLists.txt @@ -53,6 +53,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) BUILD_DEPENDENCIES PUBLIC Gem::${Name}.Editor.Static + RUNTIME_DEPENDENCIES + Gem::QtForPython.Editor ) # By default, we will specify that the above target ${Name} would be used by diff --git a/Templates/PythonToolGem/Template/gem.json b/Templates/PythonToolGem/Template/gem.json index d4ff637bee..84f5b65a3e 100644 --- a/Templates/PythonToolGem/Template/gem.json +++ b/Templates/PythonToolGem/Template/gem.json @@ -13,5 +13,8 @@ "${Name}" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "dependencies": [ + "QtForPython" + ] } From caf1c18fbe8bd84d6788615323ac6e9f23732738 Mon Sep 17 00:00:00 2001 From: chiyenteng <82238204+chiyenteng@users.noreply.github.com> Date: Tue, 9 Nov 2021 12:40:56 -0800 Subject: [PATCH 23/35] Prevent track editor view's default size to be zero (#5453) * Prevent track editor view's default size to be zero Signed-off-by: chiyteng * minor rewording Signed-off-by: chiyteng --- Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp index e6c2dda74c..9ad9a50aa5 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.cpp @@ -257,6 +257,7 @@ BOOL CUiAnimViewDialog::OnInitDialog() m_wndSplitter->addWidget(m_wndDopeSheet); m_wndSplitter->setStretchFactor(0, 1); m_wndSplitter->setStretchFactor(1, 10); + m_wndSplitter->setChildrenCollapsible(false); l->addWidget(m_wndSplitter); w->setLayout(l); setCentralWidget(w); @@ -283,6 +284,11 @@ BOOL CUiAnimViewDialog::OnInitDialog() m_wndCurveEditorDock->setVisible(false); m_wndCurveEditorDock->setEnabled(false); + // In order to prevent the track editor view from collapsing and becoming invisible, we use the + // minimum size of the curve editor for the track editor as well. Since both editors use the same + // view widget in the UI animation editor when not in 'Both' mode, the sizes can be identical. + m_wndDopeSheet->setMinimumSize(m_wndCurveEditor->minimumSizeHint()); + InitSequences(); m_lazyInitDone = false; From 461b63c61a4c4f8a45687ec1959ffe1a2401eb92 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Tue, 9 Nov 2021 14:14:13 -0800 Subject: [PATCH 24/35] Temporarily disable the platform filter (#5454) Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp index b608445d0f..acea6ce378 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterWidget.cpp @@ -221,7 +221,6 @@ namespace O3DE::ProjectManager ResetGemStatusFilter(); ResetGemOriginFilter(); ResetTypeFilter(); - ResetPlatformFilter(); ResetFeatureFilter(); } From 15586ee53e0e8a627cee52bc54905e772ee4cbfc Mon Sep 17 00:00:00 2001 From: moraaar Date: Tue, 9 Nov 2021 23:42:01 +0000 Subject: [PATCH 25/35] Adding missing pragma once at XcbInputDeviceMouse.h (#5448) Signed-off-by: moraaar --- .../Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h index a69a8a9ec5..f5b805a7a5 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceMouse.h @@ -6,6 +6,8 @@ * */ +#pragma once + #include #include #include From 31439eb7c85c91d39835f43c79d904e3375f5afe Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Tue, 9 Nov 2021 17:52:26 -0600 Subject: [PATCH 26/35] Adding m_exposure field to terrain's object srg to sync it with the default object srg. (#5462) Signed-off-by: Ken Pruiksma --- Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli index cd680f721a..52d0e0a6cc 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli @@ -56,6 +56,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject float m_padding; bool m_useReflectionProbe; bool m_useParallaxCorrection; + float m_exposure; }; ReflectionProbeData m_reflectionProbeData; From 0e3df14ea2f1b2e36c3d64cf6ff72b52eb2d2f5a Mon Sep 17 00:00:00 2001 From: John Date: Wed, 10 Nov 2021 11:59:28 +0000 Subject: [PATCH 27/35] Add missing bus connection/disconnection. Signed-off-by: John --- .../UI/PropertyEditor/EntityPropertyEditor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index 9ffe8021e3..a449fa0055 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -606,6 +606,7 @@ namespace AzToolsFramework AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect( AzToolsFramework::GetEntityContextId()); + ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId()); } EntityPropertyEditor::~EntityPropertyEditor() @@ -618,7 +619,8 @@ namespace AzToolsFramework AZ::EntitySystemBus::Handler::BusDisconnect(); EditorEntityContextNotificationBus::Handler::BusDisconnect(); AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); - + ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); + for (auto& entityId : m_overrideSelectedEntityIds) { DisconnectFromEntityBuses(entityId); From 027b0f86ae5bac33ae04967eb66bf5927df1face Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Wed, 10 Nov 2021 14:41:59 +0100 Subject: [PATCH 28/35] Activate AssetBrowserTableView feature (#5367) Signed-off-by: igarri --- .../AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index acf935e6dc..c6772ea2d7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -20,7 +20,7 @@ AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") AZ_POP_DISABLE_WARNING AZ_CVAR( - bool, ed_useNewAssetBrowserTableView, false, nullptr, AZ::ConsoleFunctorFlags::Null, + bool, ed_useNewAssetBrowserTableView, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new AssetBrowser TableView for searching assets."); namespace AzToolsFramework { From 847e13154f2b95947561b07ad00b8420764916de Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 10 Nov 2021 09:55:49 -0600 Subject: [PATCH 29/35] Updated some Script Canvas node slot names to EntityID for consistency. Signed-off-by: Chris Galvan --- Assets/Editor/Translation/scriptcanvas_en_us.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Assets/Editor/Translation/scriptcanvas_en_us.ts b/Assets/Editor/Translation/scriptcanvas_en_us.ts index 7b8361c879..6d436b7caf 100644 --- a/Assets/Editor/Translation/scriptcanvas_en_us.ts +++ b/Assets/Editor/Translation/scriptcanvas_en_us.ts @@ -62164,7 +62164,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGADDED_OUTPUT0_TOOLTIP @@ -62202,7 +62202,7 @@ An Entity can be selected by using the pick button, or by dragging an Entity fro HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityId HANDLER_TAGGLOBALNOTIFICATIONBUS_ONENTITYTAGREMOVED_OUTPUT0_TOOLTIP @@ -81852,7 +81852,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_SPAWNERCOMPONENTNOTIFICATIONBUS_ONENTITYSPAWNED_OUTPUT1_TOOLTIP @@ -89198,7 +89198,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_ENTITYBUS_ONENTITYACTIVATED_OUTPUT0_TOOLTIP @@ -89236,7 +89236,7 @@ The element is removed from its current parent and added as a child of the new p HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_NAME Simple Type: EntityID C++ Type: const EntityId& - Entity + EntityID HANDLER_ENTITYBUS_ONENTITYDEACTIVATED_OUTPUT0_TOOLTIP From f0b4eb17127534ca0919cb9eb372439e2739f5de Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 10 Nov 2021 10:54:53 -0600 Subject: [PATCH 30/35] update comment and error message Signed-off-by: Guthrie Adams --- .../RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp | 5 ++++- .../RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp index 37bd5a19f2..14ef3bb17d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/LuaMaterialFunctorSourceData.cpp @@ -137,7 +137,10 @@ namespace AZ } else if (!m_luaSourceFile.empty()) { - auto loadOutcome = RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); + // The sub ID for script assets must be explicit. + // LUA source files output a compiled as well as an uncompiled asset, sub Ids of 1 and 2. + auto loadOutcome = + RPI::AssetUtils::LoadAsset(materialTypeSourceFilePath, m_luaSourceFile, ScriptAsset::CompiledAssetSubId); if (!loadOutcome) { AZ_Error("LuaMaterialFunctorSourceData", false, "Could not load script file '%s'", m_luaSourceFile.c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp index e5466a173f..d6308ec655 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceData.cpp @@ -250,7 +250,7 @@ namespace AZ const auto parentTypeAssetId = AssetUtils::MakeAssetId(parentSourceAbsPath, parentSourceData.m_materialType, 0); if (!parentTypeAssetId) { - AZ_Error("MaterialSourceData", false, "Parent material asset ID isn't valid: '%s'.", parentSourceAbsPath.c_str()); + AZ_Error("MaterialSourceData", false, "Parent material asset ID wasn't found: '%s'.", parentSourceAbsPath.c_str()); return Failure(); } From 7159e3fe575378254983e09dabe44a9ef52e53c7 Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Wed, 10 Nov 2021 17:22:55 +0000 Subject: [PATCH 31/35] Moving to stabilization Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp | 162 +++++++++--------- 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp index 3778ba860f..9de441eecf 100644 --- a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp +++ b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp @@ -6,15 +6,13 @@ * */ +#include + #include #include #include -#include - #include -#include -#include #include #include @@ -23,21 +21,12 @@ using ::testing::NiceMock; using ::testing::AtLeast; using ::testing::_; -using ::testing::NiceMock; -using ::testing::AtLeast; -using ::testing::_; - class LayerSpawnerComponentTest : public ::testing::Test { protected: AZ::ComponentApplication m_app; - AZStd::unique_ptr m_entity; - Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent; - UnitTest::MockAxisAlignedBoxShapeComponent* m_shapeComponent; - AZStd::unique_ptr> m_terrainSystem; - void SetUp() override { AZ::ComponentApplication::Descriptor appDesc; @@ -50,78 +39,86 @@ protected: void TearDown() override { - m_entity.reset(); - m_terrainSystem.reset(); m_app.Destroy(); } - void CreateEntity() + AZStd::unique_ptr CreateEntity() { - m_entity = AZStd::make_unique(); - m_entity->Init(); + auto entity = AZStd::make_unique(); + entity->Init(); - ASSERT_TRUE(m_entity); - } - - void AddLayerSpawnerAndShapeComponentToEntity() - { - AddLayerSpawnerAndShapeComponentToEntity(Terrain::TerrainLayerSpawnerConfig()); + return entity; } - void AddLayerSpawnerAndShapeComponentToEntity(const Terrain::TerrainLayerSpawnerConfig& config) + Terrain::TerrainLayerSpawnerComponent* AddLayerSpawnerToEntity(AZ::Entity* entity, const Terrain::TerrainLayerSpawnerConfig& config) { - m_layerSpawnerComponent = m_entity->CreateComponent(config); - m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor()); + auto layerSpawnerComponent = entity->CreateComponent(config); + m_app.RegisterComponentDescriptor(layerSpawnerComponent->CreateDescriptor()); - m_shapeComponent = m_entity->CreateComponent(); - m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor()); - - ASSERT_TRUE(m_layerSpawnerComponent); - ASSERT_TRUE(m_shapeComponent); + return layerSpawnerComponent; } - void CreateMockTerrainSystem() + UnitTest::MockAxisAlignedBoxShapeComponent* AddShapeComponentToEntity(AZ::Entity* entity) { - m_terrainSystem = AZStd::make_unique>(); + UnitTest::MockAxisAlignedBoxShapeComponent* shapeComponent = entity->CreateComponent(); + m_app.RegisterComponentDescriptor(shapeComponent->CreateDescriptor()); + + return shapeComponent; } }; -TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess) +TEST_F(LayerSpawnerComponentTest, ActivateEntityWithoutShapeFails) +{ + auto entity = CreateEntity(); + + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + + const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails(); + EXPECT_FALSE(sortOutcome.IsSuccess()); + + entity.reset(); +} + +TEST_F(LayerSpawnerComponentTest, ActivateEntityActivateSuccess) { - CreateEntity(); - AddLayerSpawnerAndShapeComponentToEntity(); + auto entity = CreateEntity(); + + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); - EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active); - - m_entity->Deactivate(); + entity->Activate(); + EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active); + + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect) { - CreateEntity(); - AddLayerSpawnerAndShapeComponentToEntity(); + auto entity = CreateEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); AZ::u32 priority = 999, layer = 999; - Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); EXPECT_EQ(0, priority); EXPECT_EQ(1, layer); bool useGroundPlane = false; - Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + Terrain::TerrainSpawnerRequestBus::EventResult( + useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); EXPECT_TRUE(useGroundPlane); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) { - CreateEntity(); + auto entity = CreateEntity(); constexpr static AZ::u32 testPriority = 15; constexpr static AZ::u32 testLayer = 0; @@ -131,12 +128,13 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) config.m_priority = testPriority; config.m_useGroundPlane = false; - AddLayerSpawnerAndShapeComponentToEntity(config); + AddLayerSpawnerToEntity(entity.get(), config); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); AZ::u32 priority = 999, layer = 999; - Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); + Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority); EXPECT_EQ(testPriority, priority); EXPECT_EQ(testLayer, layer); @@ -144,82 +142,86 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) bool useGroundPlane = true; Terrain::TerrainSpawnerRequestBus::EventResult( - useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); + useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane); EXPECT_FALSE(useGroundPlane); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The Activate call should register the area. - EXPECT_CALL(*m_terrainSystem, RegisterArea(_)).Times(1); + EXPECT_CALL(terrainSystem, RegisterArea(_)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The Deactivate call should unregister the area. - EXPECT_CALL(*m_terrainSystem, UnregisterArea(_)).Times(1); + EXPECT_CALL(terrainSystem, UnregisterArea(_)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The TransformChanged call should refresh the area. - EXPECT_CALL(*m_terrainSystem, RefreshArea(_, _)).Times(1); + EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); // The component gets transform change notifications via the shape bus. LmbrCentral::ShapeComponentNotificationsBus::Event( - m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, + entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::TransformChanged); - m_entity->Deactivate(); + entity.reset(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) { - CreateEntity(); + auto entity = CreateEntity(); - CreateMockTerrainSystem(); + NiceMock terrainSystem; // The ShapeChanged call should refresh the area. - EXPECT_CALL(*m_terrainSystem, RefreshArea(_, _)).Times(1); + EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1); - AddLayerSpawnerAndShapeComponentToEntity(); + AddLayerSpawnerToEntity(entity.get(), Terrain::TerrainLayerSpawnerConfig()); + AddShapeComponentToEntity(entity.get()); - m_entity->Activate(); + entity->Activate(); - LmbrCentral::ShapeComponentNotificationsBus::Event( - m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, + LmbrCentral::ShapeComponentNotificationsBus::Event( + entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged); - m_entity->Deactivate(); + entity.reset(); } From 0c546828d642b5a71e2762a8dbe419acbf3a3400 Mon Sep 17 00:00:00 2001 From: SJ Date: Wed, 10 Nov 2021 09:31:59 -0800 Subject: [PATCH 32/35] 1. Add nullptr checks to prevent crashes when non-critical shaders fail to compile. (#5451) 2. Add a higher "launch_ap_timeout" for Mac because launching a newly built/downloaded AP can take a while. Signed-off-by: amzn-sj --- .../PostProcessing/BlendColorGradingLutsPass.cpp | 6 +++++- .../ReflectionProbeFeatureProcessor.cpp | 7 ++++++- .../RPI.Public/Pass/FullscreenTrianglePass.cpp | 6 ++++++ Registry/Platform/Mac/bootstrap_overrides.setreg | 12 ++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Registry/Platform/Mac/bootstrap_overrides.setreg diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp index f74837bd9a..ca93898d5e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp @@ -46,7 +46,11 @@ namespace AZ void BlendColorGradingLutsPass::InitializeShaderVariant() { - AZ_Assert(m_shader != nullptr, "BlendColorGradingLutsPass %s has a null shader when calling InitializeShaderVariant.", GetPathName().GetCStr()); + if (m_shader == nullptr) + { + AZ_Assert(false, "BlendColorGradingLutsPass %s has a null shader when calling InitializeShaderVariant.", GetPathName().GetCStr()); + return; + } // Total variations is MaxBlendLuts plus one for the fallback case that none of the LUTs are found, // and hence zero LUTs are blended resulting in an identity LUT. diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index b1484ac8a8..e9038858ad 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -443,7 +443,12 @@ namespace AZ { // load shader shader = RPI::LoadCriticalShader(filePath); - AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath); + + if (shader == nullptr) + { + AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to find asset for shader [%s]", filePath); + return; + } // store drawlist tag drawListTag = shader->GetDrawListTag(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp index 40dce7d138..828966f377 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/FullscreenTrianglePass.cpp @@ -136,6 +136,12 @@ namespace AZ RHI::DrawLinear draw = RHI::DrawLinear(); draw.m_vertexCount = 3; + if (m_shader == nullptr) + { + AZ_Error("PassSystem", false, "[FullscreenTrianglePass]: Shader not loaded!"); + return; + } + RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; // [GFX TODO][ATOM-872] The pass should be able to drive the shader variant diff --git a/Registry/Platform/Mac/bootstrap_overrides.setreg b/Registry/Platform/Mac/bootstrap_overrides.setreg new file mode 100644 index 0000000000..4e1ca76724 --- /dev/null +++ b/Registry/Platform/Mac/bootstrap_overrides.setreg @@ -0,0 +1,12 @@ +{ + "Amazon": { + "AzCore": { + "Bootstrap": { + // The first time an application is launched on MacOS, each + // dynamic library is inspected by the OS before being loaded. + // This can take a while on some Macs. + "launch_ap_timeout": 300 + } + } + } +} From 576248a870fb7aab37949822a54a9b3969a6a6b1 Mon Sep 17 00:00:00 2001 From: Shirang Jia Date: Wed, 10 Nov 2021 10:26:44 -0800 Subject: [PATCH 33/35] Merge Jenkinsfile from development to stabilization (#5391) Signed-off-by: shiranj --- scripts/build/Jenkins/Jenkinsfile | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 34732a5fad..beb4a21620 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -16,7 +16,7 @@ EMPTY_JSON = readJSON text: '{}' ENGINE_REPOSITORY_NAME = 'o3de' // Branches with build snapshots -BUILD_SNAPSHOTS = ['development', 'stabilization/2106'] +BUILD_SNAPSHOTS = ['development', 'stabilization/2110'] // Build snapshots with empty snapshot (for use with 'SNAPSHOT' pipeline paramater) BUILD_SNAPSHOTS_WITH_EMPTY = BUILD_SNAPSHOTS + '' @@ -102,6 +102,10 @@ def IsJobEnabled(branchName, buildTypeMap, pipelineName, platformName) { } } +def IsAPLogUpload(branchName, jobName) { + return !IsPullRequest(branchName) && jobName.toLowerCase().contains('asset') && env.AP_LOGS_S3_BUCKET +} + def GetRunningPipelineName(JENKINS_JOB_NAME) { // If the job name has an underscore def job_parts = JENKINS_JOB_NAME.tokenize('/')[0].tokenize('_') @@ -267,7 +271,7 @@ def CheckoutRepo(boolean disableSubmodules = false) { palRm('commitdate') } -def HandleDriveMount(String snapshot, String repositoryName, String projectName, String pipeline, String branchName, String platform, String buildType, String workspace, boolean recreateVolume = false) { +def HandleDriveMount(String snapshot, String repositoryName, String projectName, String pipeline, String branchName, String platform, String buildType, String workspace, boolean recreateVolume = false) { unstash name: 'incremental_build_script' def pythonCmd = '' @@ -429,6 +433,27 @@ def ExportTestScreenshots(Map options, String branchName, String platformName, S } } +def UploadAPLogs(Map options, String branchName, String platformName, String jobName, String workspace, Map params) { + dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { + projects = params.CMAKE_LY_PROJECTS.split(",") + projects.each{ project -> + def apLogsPath = "${project}/user/log" + def s3UploadScriptPath = "scripts/build/tools/upload_to_s3.py" + if(env.IS_UNIX) { + pythonPath = "${options.PYTHON_DIR}/python.sh" + } + else { + pythonPath = "${options.PYTHON_DIR}/python.cmd" + } + def command = "${pythonPath} -u ${s3UploadScriptPath} --base_dir ${apLogsPath} " + + "--file_regex \".*\" --bucket ${env.AP_LOGS_S3_BUCKET} " + + "--search_subdirectories True --key_prefix ${env.JENKINS_JOB_NAME}/${branchName}/${env.BUILD_NUMBER}/${platformName}/${jobName} " + + '--extra_args {\\"ACL\\":\\"bucket-owner-full-control\\"}' + palSh(command, "Uploading AP logs for job ${jobName} for branch ${branchName}", false) + } + } + } + def PostBuildCommonSteps(String workspace, boolean mount = true) { echo 'Starting post-build common steps...' @@ -492,6 +517,14 @@ def CreateExportTestScreenshotsStage(Map pipelineConfig, String branchName, Stri } } +def CreateUploadAPLogsStage(Map pipelineConfig, String branchName, String platformName, String jobName, String workspace, Map params) { + return { + stage("${jobName}_upload_ap_logs") { + UploadAPLogs(pipelineConfig, branchName, platformName, jobName, workspace, params) + } + } +} + def CreateTeardownStage(Map environmentVars) { return { stage('Teardown') { @@ -516,9 +549,11 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar CreateSetupStage(pipelineConfig, snapshot, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars, onlyMountEBSVolume).call() if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages + pipelineEnvVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) build_job.value.steps.each { build_step -> build_job_name = build_step - envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + // This addition of maps makes it that the right operand will override entries if they overlap with the left operand + envVars = pipelineEnvVars + GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) try { CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() } @@ -541,6 +576,9 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar error "Node disconnected during build: ${e}" // Error raised to retry stage on a new node } } + if (IsAPLogUpload(branchName, build_job_name)) { + CreateUploadAPLogsStage(pipelineConfig, branchName, platform.key, build_job_name, envVars['WORKSPACE'], platform.value.build_types[build_job_name].PARAMETERS).call() + } // All other errors will be raised outside the retry block currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' currentException = e.toString() @@ -768,6 +806,7 @@ try { platform.value.build_types.each { build_job -> if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + envVars['JENKINS_JOB_NAME'] = env.JOB_NAME // Save original Jenkins job name to JENKINS_JOB_NAME envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this someBuildHappened = true From f2e191ea77c64232fb1fabf8f02ac235c3704518 Mon Sep 17 00:00:00 2001 From: AMZN-Phil Date: Wed, 10 Nov 2021 10:28:32 -0800 Subject: [PATCH 34/35] Fix trying to remove a cache file Signed-off-by: AMZN-Phil --- scripts/o3de/o3de/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/o3de/o3de/utils.py b/scripts/o3de/o3de/utils.py index 56f9ae4bcd..9872c0779b 100755 --- a/scripts/o3de/o3de/utils.py +++ b/scripts/o3de/o3de/utils.py @@ -128,7 +128,7 @@ def download_file(parsed_uri, download_path: pathlib.Path, force_overwrite, down logger.warn(f'File already downloaded to {download_path}.') else: try: - shutil.rmtree(download_path) + os.unlink(download_path) except OSError: logger.error(f'Could not remove existing download path {download_path}.') return 1 From e0cc86e8985b93e836a72772910ae304ef26cc3c Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Wed, 10 Nov 2021 13:21:42 -0600 Subject: [PATCH 35/35] Remove AssetProcessorManagerTest AssertAbsorber and update test to use the one from the base class instead (#5216) (#5381) Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> (cherry picked from commit b3301414ad1f76161fa88eaf8650f42bfb94617c) # Conflicts: # Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp --- .../AssetProcessorManagerTest.cpp | 32 +++++++++---------- .../assetmanager/AssetProcessorManagerTest.h | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp index f8d758e092..1a6063cff0 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp @@ -243,7 +243,7 @@ void AssetProcessorManagerTest::SetUp() m_mockApplicationManager->BusConnect(); m_assetProcessorManager.reset(new AssetProcessorManager_Test(m_config.get())); - m_assertAbsorber.Clear(); + m_errorAbsorber->Clear(); m_isIdling = false; @@ -334,9 +334,9 @@ TEST_F(AssetProcessorManagerTest, UnitTestForGettingJobInfoBySourceUUIDSuccess) EXPECT_STRCASEEQ(relFileName.toUtf8().data(), response.m_jobList[0].m_sourceFile.c_str()); EXPECT_STRCASEEQ(tempPath.filePath("subfolder1").toUtf8().data(), response.m_jobList[0].m_watchFolder.c_str()); - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToDatabase) @@ -388,9 +388,9 @@ TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToD ASSERT_EQ(response.m_jobList[0].m_warningCount, 11); ASSERT_EQ(response.m_jobList[0].m_errorCount, 22); - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); } @@ -1312,8 +1312,8 @@ void PathDependencyTest::SetUp() void PathDependencyTest::TearDown() { - ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0); - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0); AssetProcessorManagerTest::TearDown(); } @@ -1617,7 +1617,7 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency mainFile.m_products.push_back(productAssetId); // tell the APM that the asset has been processed and allow it to bubble through its event queue: - m_assertAbsorber.Clear(); + m_errorAbsorber->Clear(); m_assetProcessorManager->AssetProcessed(jobDetails.m_jobEntry, processJobResponse); ASSERT_TRUE(BlockUntilIdle(5000)); @@ -1627,8 +1627,8 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency ASSERT_TRUE(dependencyContainer.empty()); // We are testing 2 different dependencies, so we should get 2 warnings - ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 2); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 2); + m_errorAbsorber->Clear(); } // This test shows the process of deferring resolution of a path dependency works. @@ -1945,8 +1945,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludePathsExisting_ResolveCorr ); // Test asset PrimaryFile1 has 4 conflict dependencies - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 4); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 4); + m_errorAbsorber->Clear(); } TEST_F(PathDependencyTest, WildcardDependencies_Deferred_ResolveCorrectly) @@ -2093,8 +2093,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludedPathDeferred_ResolveCorr // Test asset PrimaryFile1 has 4 conflict dependencies // After test assets dep2 and dep3 are processed, // another 2 errors will be raised because of the confliction - ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 6); - m_assertAbsorber.Clear(); + ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 6); + m_errorAbsorber->Clear(); } void PathDependencyTest::RunWildcardTest(bool useCorrectDatabaseSeparator, AssetBuilderSDK::ProductPathDependencyType pathDependencyType, bool buildDependenciesFirst) diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h index 3443a4c519..2f0121485e 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h @@ -58,7 +58,6 @@ protected: AZStd::unique_ptr m_assetProcessorManager; AZStd::unique_ptr m_mockApplicationManager; AZStd::unique_ptr m_config; - UnitTestUtils::AssertAbsorber m_assertAbsorber; // absorb asserts/warnings/errors so that the unit test output is not cluttered QString m_gameName; QDir m_normalizedCacheRootDir; AZStd::atomic_bool m_isIdling;