Merge pull request #3035 from aws-lumberyard-dev/Atom/antonmic/PassBuilder

Changing pass builder to declare job dependencies on referenced .shader files and consequently removing the critical flag from the shader builder.
monroegm-disable-blank-issue-2
antonmic 4 years ago committed by GitHub
commit 7d4022fbdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -139,8 +139,7 @@ namespace AZ
AssetBuilderSDK::JobDescriptor jobDescriptor; AssetBuilderSDK::JobDescriptor jobDescriptor;
jobDescriptor.m_priority = 2; jobDescriptor.m_priority = 2;
// [GFX TODO][ATOM-2830] Set 'm_critical' back to 'false' once proper fix for Atom startup issues are in jobDescriptor.m_critical = false;
jobDescriptor.m_critical = true;
jobDescriptor.m_jobKey = ShaderAssetBuilderJobKey; jobDescriptor.m_jobKey = ShaderAssetBuilderJobKey;
jobDescriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str()); jobDescriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
jobDescriptor.m_jobParameters.emplace(ShaderAssetBuildTimestampParam, AZStd::to_string(shaderAssetBuildTimestamp)); jobDescriptor.m_jobParameters.emplace(ShaderAssetBuildTimestampParam, AZStd::to_string(shaderAssetBuildTimestamp));

@ -322,7 +322,7 @@ namespace AZ
{ {
const char* auxGeomWorldShaderFilePath = "Shaders/auxgeom/auxgeomworld.azshader"; const char* auxGeomWorldShaderFilePath = "Shaders/auxgeom/auxgeomworld.azshader";
m_shader = RPI::LoadShader(auxGeomWorldShaderFilePath); m_shader = RPI::LoadCriticalShader(auxGeomWorldShaderFilePath);
if (!m_shader) if (!m_shader)
{ {
AZ_Error("DynamicPrimitiveProcessor", false, "Failed to get shader"); AZ_Error("DynamicPrimitiveProcessor", false, "Failed to get shader");

@ -1385,9 +1385,9 @@ namespace AZ
const char* litObjectShaderFilePath = "Shaders/auxgeom/auxgeomobjectlit.azshader"; const char* litObjectShaderFilePath = "Shaders/auxgeom/auxgeomobjectlit.azshader";
// constant color shader // constant color shader
m_unlitShader = RPI::LoadShader(unlitObjectShaderFilePath); m_unlitShader = RPI::LoadCriticalShader(unlitObjectShaderFilePath);
// direction light shader // direction light shader
m_litShader = RPI::LoadShader(litObjectShaderFilePath); m_litShader = RPI::LoadCriticalShader(litObjectShaderFilePath);
if (m_unlitShader.get() == nullptr || m_litShader == nullptr) if (m_unlitShader.get() == nullptr || m_litShader == nullptr)
{ {

@ -38,7 +38,7 @@ namespace AZ
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistance.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistance.azshader";
m_shader = RPI::LoadShader(shaderFilePath); m_shader = RPI::LoadCriticalShader(shaderFilePath);
if (m_shader == nullptr) if (m_shader == nullptr)
{ {
return; return;

@ -38,7 +38,7 @@ namespace AZ
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiance.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiance.azshader";
m_shader = RPI::LoadShader(shaderFilePath); m_shader = RPI::LoadCriticalShader(shaderFilePath);
if (m_shader == nullptr) if (m_shader == nullptr)
{ {
return; return;

@ -51,7 +51,7 @@ namespace AZ
{ {
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
shader = RPI::LoadShader(shaderFilePath); shader = RPI::LoadCriticalShader(shaderFilePath);
if (shader == nullptr) if (shader == nullptr)
{ {
return; return;

@ -42,7 +42,7 @@ namespace AZ
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridClassification.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridClassification.azshader";
m_shader = RPI::LoadShader(shaderFilePath); m_shader = RPI::LoadCriticalShader(shaderFilePath);
if (m_shader == nullptr) if (m_shader == nullptr)
{ {
return; return;

@ -74,7 +74,7 @@ namespace AZ
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
Data::Instance<RPI::Shader> shader = RPI::LoadShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"); Data::Instance<RPI::Shader> shader = RPI::LoadCriticalShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader");
if (shader) if (shader)
{ {
m_probeGridRenderData.m_drawListTag = shader->GetDrawListTag(); m_probeGridRenderData.m_drawListTag = shader->GetDrawListTag();

@ -52,7 +52,7 @@ namespace AZ
// load the ray tracing shader // load the ray tracing shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracing.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracing.azshader";
m_rayTracingShader = RPI::LoadShader(shaderFilePath); m_rayTracingShader = RPI::LoadCriticalShader(shaderFilePath);
if (m_rayTracingShader == nullptr) if (m_rayTracingShader == nullptr)
{ {
return; return;
@ -64,7 +64,7 @@ namespace AZ
// closest hit shader // closest hit shader
AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingClosestHit.azshader"; AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingClosestHit.azshader";
m_closestHitShader = RPI::LoadShader(closestHitShaderFilePath); m_closestHitShader = RPI::LoadCriticalShader(closestHitShaderFilePath);
auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor; RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor;
@ -72,7 +72,7 @@ namespace AZ
// miss shader // miss shader
AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingMiss.azshader"; AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingMiss.azshader";
m_missShader = RPI::LoadShader(missShaderFilePath); m_missShader = RPI::LoadCriticalShader(missShaderFilePath);
auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor; RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor;

@ -42,7 +42,7 @@ namespace AZ
// load shader // load shader
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRelocation.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRelocation.azshader";
m_shader = RPI::LoadShader(shaderFilePath); m_shader = RPI::LoadCriticalShader(shaderFilePath);
if (m_shader == nullptr) if (m_shader == nullptr)
{ {
return; return;

@ -30,7 +30,7 @@ namespace AZ
// create the shader resource group // create the shader resource group
// Note: the shader may not be available on all platforms // Note: the shader may not be available on all platforms
AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader"; AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader";
m_shader = RPI::LoadShader(shaderFilePath); m_shader = RPI::LoadCriticalShader(shaderFilePath);
if (m_shader == nullptr) if (m_shader == nullptr)
{ {
return; return;

@ -446,7 +446,7 @@ namespace AZ
} }
{ {
m_shader = RPI::LoadShader(ImguiShaderFilePath); m_shader = RPI::LoadCriticalShader(ImguiShaderFilePath);
m_pipelineState = aznew RPI::PipelineStateForDraw; m_pipelineState = aznew RPI::PipelineStateForDraw;
m_pipelineState->Init(m_shader); m_pipelineState->Init(m_shader);

@ -487,7 +487,7 @@ namespace AZ
RHI::DrawListTag& drawListTag) RHI::DrawListTag& drawListTag)
{ {
// load shader // load shader
shader = RPI::LoadShader(filePath); shader = RPI::LoadCriticalShader(filePath);
AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath); AZ_Error("ReflectionProbeFeatureProcessor", shader, "Failed to find asset for shader [%s]", filePath);
// store drawlist tag // store drawlist tag

@ -52,7 +52,7 @@ namespace AZ
// load shaders // load shaders
AZStd::string verticalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurVertical.azshader"; AZStd::string verticalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurVertical.azshader";
Data::Instance<AZ::RPI::Shader> verticalBlurShader = RPI::LoadShader(verticalBlurShaderFilePath); Data::Instance<AZ::RPI::Shader> verticalBlurShader = RPI::LoadCriticalShader(verticalBlurShaderFilePath);
if (verticalBlurShader == nullptr) if (verticalBlurShader == nullptr)
{ {
AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), verticalBlurShaderFilePath.c_str()); AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), verticalBlurShaderFilePath.c_str());
@ -60,7 +60,7 @@ namespace AZ
} }
AZStd::string horizontalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.azshader"; AZStd::string horizontalBlurShaderFilePath = "Shaders/Reflections/ReflectionScreenSpaceBlurHorizontal.azshader";
Data::Instance<AZ::RPI::Shader> horizontalBlurShader = RPI::LoadShader(horizontalBlurShaderFilePath); Data::Instance<AZ::RPI::Shader> horizontalBlurShader = RPI::LoadCriticalShader(horizontalBlurShaderFilePath);
if (horizontalBlurShader == nullptr) if (horizontalBlurShader == nullptr)
{ {
AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), horizontalBlurShaderFilePath.c_str()); AZ_Error("PassSystem", false, "[ReflectionScreenSpaceBlurPass '%s']: Failed to load shader '%s'!", GetPathName().GetCStr(), horizontalBlurShaderFilePath.c_str());

@ -22,19 +22,21 @@ namespace AZ
class Shader; class Shader;
//! Get the asset ID for a given shader file path //! Get the asset ID for a given shader file path
Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath); Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical = false);
//! Finds a shader asset for the given shader asset ID. Optional shaderFilePath param for debugging. //! Finds a shader asset for the given shader asset ID. Optional shaderFilePath param for debugging.
Data::Asset<ShaderAsset> FindShaderAsset(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); Data::Asset<ShaderAsset> FindShaderAsset(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = "");
//! Finds a shader asset for the given shader file path //! Finds a shader asset for the given shader file path
Data::Asset<ShaderAsset> FindShaderAsset(const AZStd::string& shaderFilePath); Data::Asset<ShaderAsset> FindShaderAsset(const AZStd::string& shaderFilePath);
Data::Asset<ShaderAsset> FindCriticalShaderAsset(const AZStd::string& shaderFilePath);
//! Loads a shader for the given shader asset ID. Optional shaderFilePath param for debugging. //! Loads a shader for the given shader asset ID. Optional shaderFilePath param for debugging.
Data::Instance<Shader> LoadShader(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = ""); Data::Instance<Shader> LoadShader(Data::AssetId shaderAssetId, const AZStd::string& shaderFilePath = "");
//! Loads a shader for the given shader file path //! Loads a shader for the given shader file path
Data::Instance<Shader> LoadShader(const AZStd::string& shaderFilePath); Data::Instance<Shader> LoadShader(const AZStd::string& shaderFilePath);
Data::Instance<Shader> LoadCriticalShader(const AZStd::string& shaderFilePath);
//! Loads a streaming image asset for the given file path //! Loads a streaming image asset for the given file path
Data::Instance<RPI::StreamingImage> LoadStreamingTexture(AZStd::string_view path); Data::Instance<RPI::StreamingImage> LoadStreamingTexture(AZStd::string_view path);

@ -37,7 +37,7 @@ namespace AZ
{ {
AssetBuilderSDK::AssetBuilderDesc builder; AssetBuilderSDK::AssetBuilderDesc builder;
builder.m_name = PassBuilderJobKey; builder.m_name = PassBuilderJobKey;
builder.m_version = 12; // ATOM-15472 builder.m_version = 13; // antonmic: making .pass files declare dependency on shaders they reference
builder.m_busId = azrtti_typeid<PassBuilder>(); builder.m_busId = azrtti_typeid<PassBuilder>();
builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
@ -65,36 +65,52 @@ namespace AZ
m_isShuttingDown = true; m_isShuttingDown = true;
} }
void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const // --- Code related to dependency shader asset handling ---
// Helper class to pass parameters to the AddDependency and FindReferencedAssets functions below
struct FindPassReferenceAssetParams
{ {
if (m_isShuttingDown) void* passAssetObject = nullptr;
Uuid passAssetUuid;
SerializeContext* serializeContext = nullptr;
AZStd::string_view passAssetSourceFile; // File path of the pass asset
AZStd::string_view dependencySourceFile; // File pass of the asset the pass asset depends on
const char* jobKey = nullptr; // Job key for adding job dependency
};
// Helper function to get a file reference and create a corresponding job dependency
bool AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job)
{
AZStd::string_view& file = params.dependencySourceFile;
AZ::Data::AssetInfo sourceInfo;
AZStd::string watchFolder;
bool fileFound = false;
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.data(), sourceInfo, watchFolder);
if (fileFound)
{ {
response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown; AssetBuilderSDK::JobDependency jobDependency;
return; jobDependency.m_jobKey = params.jobKey;
jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
jobDependency.m_sourceFile.m_sourceFileDependencyPath = file;
job->m_jobDependencyList.push_back(jobDependency);
AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data());
return true;
} }
else
for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
{ {
AssetBuilderSDK::JobDescriptor job; AZ_Error(PassBuilderName, false, "Could not find referenced file [%s]", file.data());
job.m_jobKey = PassBuilderJobKey; return false;
job.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
// Passes are a critical part of the rendering system
job.m_critical = true;
response.m_createJobOutputs.push_back(job);
} }
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
} }
// Helper function to find all assetId's and object references // Helper function to find all assetId's and object references
bool PassBuilder::FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set<Data::AssetId> &referencedAssetList) const bool FindReferencedAssets(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job)
{ {
SerializeContext::ErrorHandler errorLogger; SerializeContext::ErrorHandler errorLogger;
errorLogger.Reset(); errorLogger.Reset();
bool foundProblems = false; bool success = true;
// This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references // This callback will check whether the given element is an asset reference. If so, it will add it to the list of asset references
auto beginCallback = [&](void* ptr, const SerializeContext::ClassData* classData, [[maybe_unused]] const SerializeContext::ClassElement* classElement) auto beginCallback = [&](void* ptr, const SerializeContext::ClassData* classData, [[maybe_unused]] const SerializeContext::ClassElement* classElement)
@ -103,31 +119,34 @@ namespace AZ
if (classData->m_typeId == azrtti_typeid<AssetReference>()) if (classData->m_typeId == azrtti_typeid<AssetReference>())
{ {
AssetReference* assetReference = reinterpret_cast<AssetReference*>(ptr); AssetReference* assetReference = reinterpret_cast<AssetReference*>(ptr);
// If the asset id isn't already provided, get it using the source file path // If the asset id isn't already provided, get it using the source file path
if (!assetReference->m_assetId.IsValid() && !assetReference->m_filePath.empty()) if (!assetReference->m_assetId.IsValid() && !assetReference->m_filePath.empty())
{ {
AZStd::string path = assetReference->m_filePath; const AZStd::string& path = assetReference->m_filePath;
uint32_t subId = 0; uint32_t subId = 0;
auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId); if (job != nullptr) // Create Job Phase
if (assetIdOutcome)
{ {
assetReference->m_assetId = assetIdOutcome.GetValue(); params.dependencySourceFile = path;
bool dependencyAddedSuccessfully = AddDependency(params, job);
success = dependencyAddedSuccessfully && success;
} }
else else // Process Job Phase
{ {
AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str()); auto assetIdOutcome = AssetUtils::MakeAssetId(path, subId);
foundProblems = true;
if (assetIdOutcome)
{
assetReference->m_assetId = assetIdOutcome.GetValue();
}
else
{
AZ_Error(PassBuilderName, false, "Could not get AssetId for [%s]", assetReference->m_filePath.c_str());
success = false;
}
} }
} }
// If the asset ID is valid, add it as a dependency
if (assetReference->m_assetId.IsValid())
{
referencedAssetList.insert(assetReference->m_assetId);
}
} }
return true; return true;
}; };
@ -136,26 +155,100 @@ namespace AZ
SerializeContext::EnumerateInstanceCallContext callContext( SerializeContext::EnumerateInstanceCallContext callContext(
AZStd::move(beginCallback), AZStd::move(beginCallback),
nullptr, nullptr,
context, params.serializeContext,
SerializeContext::ENUM_ACCESS_FOR_READ, SerializeContext::ENUM_ACCESS_FOR_READ,
&errorLogger &errorLogger
); );
// Recursively iterate over all elements in the object to find asset references with the above callback // Recursively iterate over all elements in the object to find asset references with the above callback
context->EnumerateInstance( params.serializeContext->EnumerateInstance(
&callContext &callContext
, objectPtr , params.passAssetObject
, passAssetUuid , params.passAssetUuid
, nullptr , nullptr
, nullptr , nullptr
); );
return !foundProblems; return success;
}
// --- Code related to dependency shader asset handling ---
void PassBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const
{
// --- Handle shutdown case ---
if (m_isShuttingDown)
{
response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
return;
}
// --- Get serialization context ---
SerializeContext* serializeContext = nullptr;
ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext);
if (!serializeContext)
{
AZ_Assert(false, "No serialize context");
return;
}
// --- Load PassAsset ---
AZStd::string fullPath;
AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true);
PassAsset passAsset;
AZ::Outcome<void, AZStd::string> loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, fullPath);
if (!loadResult.IsSuccess())
{
AZ_Error(PassBuilderName, false, "Failed to load pass asset [%s]", request.m_sourceFile.c_str());
AZ_Error(PassBuilderName, false, "Loading issues: %s", loadResult.GetError().data());
return;
}
AssetBuilderSDK::JobDescriptor job;
job.m_jobKey = PassBuilderJobKey;
job.m_critical = true; // Passes are a critical part of the rendering system
// --- Find all dependencies ---
AZStd::unordered_set<Data::AssetId> dependentList;
Uuid passAssetUuid = AzTypeInfo<PassAsset>::Uuid();
FindPassReferenceAssetParams params;
params.passAssetObject = &passAsset;
params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext;
params.jobKey = "Shader Asset";
if (!FindReferencedAssets(params, &job))
{
return;
}
// --- Create a job per platform ---
for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
{
for (auto& jobDependency : job.m_jobDependencyList)
{
jobDependency.m_platformIdentifier = platformInfo.m_identifier.c_str();
}
job.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
response.m_createJobOutputs.push_back(job);
}
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
} }
void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const void PassBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const
{ {
// Handle job cancellation and shutdown cases // --- Handle job cancellation and shutdown cases ---
AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId); AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId);
if (jobCancelListener.IsCancelled() || m_isShuttingDown) if (jobCancelListener.IsCancelled() || m_isShuttingDown)
{ {
@ -163,16 +256,18 @@ namespace AZ
return; return;
} }
// Get serialization context // --- Get serialization context ---
SerializeContext* context = nullptr;
ComponentApplicationBus::BroadcastResult(context, &ComponentApplicationBus::Events::GetSerializeContext); SerializeContext* serializeContext = nullptr;
if (!context) ComponentApplicationBus::BroadcastResult(serializeContext, &ComponentApplicationBus::Events::GetSerializeContext);
if (!serializeContext)
{ {
AZ_Assert(false, "No serialize context"); AZ_Assert(false, "No serialize context");
return; return;
} }
// Load PassAsset // --- Load PassAsset ---
PassAsset passAsset; PassAsset passAsset;
AZ::Outcome<void, AZStd::string> loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, request.m_fullPath); AZ::Outcome<void, AZStd::string> loadResult = JsonSerializationUtils::LoadObjectFromFile(passAsset, request.m_fullPath);
@ -183,36 +278,42 @@ namespace AZ
return; return;
} }
// Find all Asset IDs we depend on // --- Find all dependencies ---
AZStd::unordered_set<Data::AssetId> dependentList;
Uuid passAssetUuid = AzTypeInfo<PassAsset>::Uuid(); Uuid passAssetUuid = AzTypeInfo<PassAsset>::Uuid();
if (!FindPassReferencedAssets(&passAsset, passAssetUuid, context, dependentList))
FindPassReferenceAssetParams params;
params.passAssetObject = &passAsset;
params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext;
params.jobKey = "Shader Asset";
if (!FindReferencedAssets(params, nullptr))
{ {
return; return;
} }
// Get destination file name and path // --- Get destination file name and path ---
AZStd::string destFileName; AZStd::string destFileName;
AZStd::string destPath; AZStd::string destPath;
AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName); AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName);
AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true); AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true);
// Save the asset to binary format for production // --- Save the asset to binary format for production ---
bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, context);
bool result = Utils::SaveObjectToFile(destPath, DataStream::ST_BINARY, &passAsset, passAssetUuid, serializeContext);
if (result == false) if (result == false)
{ {
AZ_Error(PassBuilderName, false, "Failed to save asset to %s", destPath.c_str()); AZ_Error(PassBuilderName, false, "Failed to save asset to %s", destPath.c_str());
return; return;
} }
// Success. Save output product(s) to response // --- Save output product(s) to response ---
AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0);
for (auto& assetId : dependentList)
{
jobProduct.m_dependencies.emplace_back(AssetBuilderSDK::ProductDependency(assetId, 0));
}
jobProduct.m_dependenciesHandled = true; // We've output the dependencies immediately above so it's OK to tell the AP we've handled dependencies AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0);
jobProduct.m_dependenciesHandled = true;
response.m_outputProducts.push_back(jobProduct); response.m_outputProducts.push_back(jobProduct);
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
} }

@ -37,7 +37,6 @@ namespace AZ
void RegisterBuilder(); void RegisterBuilder();
private: private:
bool FindPassReferencedAssets(void* objectPtr, Uuid passAssetUuid, SerializeContext* context, AZStd::unordered_set<Data::AssetId> &referencedAssetList) const;
bool m_isShuttingDown = false; bool m_isShuttingDown = false;
}; };

@ -121,7 +121,7 @@ namespace AZ
// Load shader and srg // Load shader and srg
const char* ShaderPath = "shader/decomposemsimage.azshader"; const char* ShaderPath = "shader/decomposemsimage.azshader";
m_decomposeShader = LoadShader(ShaderPath); m_decomposeShader = LoadCriticalShader(ShaderPath);
if (m_decomposeShader == nullptr) if (m_decomposeShader == nullptr)
{ {

@ -8,6 +8,7 @@
#include <Atom/RHI/RHISystemInterface.h> #include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h> #include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/RPI.Public/RPIUtils.h> #include <Atom/RPI.Public/RPIUtils.h>
@ -20,7 +21,7 @@ namespace AZ
namespace RPI namespace RPI
{ {
Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath) Data::AssetId GetShaderAssetId(const AZStd::string& shaderFilePath, bool isCritical)
{ {
Data::AssetId shaderAssetId; Data::AssetId shaderAssetId;
@ -34,6 +35,19 @@ namespace AZ
if (!shaderAssetId.IsValid()) if (!shaderAssetId.IsValid())
{ {
if (isCritical)
{
Data::Asset<RPI::ShaderAsset> shaderAsset = RPI::AssetUtils::LoadCriticalAsset<RPI::ShaderAsset>(shaderFilePath);
if (shaderAsset.IsReady())
{
return shaderAsset.GetId();
}
else
{
AZ_Error("RPI Utils", false, "Could not load critical shader [%s]", shaderFilePath.c_str());
}
}
AZ_Error("RPI Utils", false, "Failed to get asset id for shader [%s]", shaderFilePath.c_str()); AZ_Error("RPI Utils", false, "Failed to get asset id for shader [%s]", shaderFilePath.c_str());
} }
@ -83,11 +97,23 @@ namespace AZ
return FindShaderAsset(GetShaderAssetId(shaderFilePath), shaderFilePath); return FindShaderAsset(GetShaderAssetId(shaderFilePath), shaderFilePath);
} }
Data::Asset<ShaderAsset> FindCriticalShaderAsset(const AZStd::string& shaderFilePath)
{
const bool isCritical = true;
return FindShaderAsset(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath);
}
Data::Instance<Shader> LoadShader(const AZStd::string& shaderFilePath) Data::Instance<Shader> LoadShader(const AZStd::string& shaderFilePath)
{ {
return LoadShader(GetShaderAssetId(shaderFilePath), shaderFilePath); return LoadShader(GetShaderAssetId(shaderFilePath), shaderFilePath);
} }
Data::Instance<Shader> LoadCriticalShader(const AZStd::string& shaderFilePath)
{
const bool isCritical = true;
return LoadShader(GetShaderAssetId(shaderFilePath, isCritical), shaderFilePath);
}
AZ::Data::Instance<RPI::StreamingImage> LoadStreamingTexture(AZStd::string_view path) AZ::Data::Instance<RPI::StreamingImage> LoadStreamingTexture(AZStd::string_view path)
{ {
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;

@ -112,9 +112,6 @@ namespace UnitTest
EXPECT_TRUE(response.m_resultCode == AssetBuilderSDK::ProcessJobResult_Success); EXPECT_TRUE(response.m_resultCode == AssetBuilderSDK::ProcessJobResult_Success);
EXPECT_TRUE(response.m_outputProducts.size() == 1); EXPECT_TRUE(response.m_outputProducts.size() == 1);
// Verify the dependency was registered
EXPECT_TRUE(response.m_outputProducts[0].m_dependencies.size() == 1);
// Verify input and output names are the same // Verify input and output names are the same
Data::Asset<Data::AssetData> readAsset = LoadAssetFromFile(response.m_outputProducts[0].m_productFileName.c_str()); Data::Asset<Data::AssetData> readAsset = LoadAssetFromFile(response.m_outputProducts[0].m_productFileName.c_str());
RPI::PassAsset* readPassAsset = static_cast<RPI::PassAsset*>(readAsset.GetData()); RPI::PassAsset* readPassAsset = static_cast<RPI::PassAsset*>(readAsset.GetData());

@ -79,7 +79,7 @@ void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapSc
// Load the shader to be used for 2d drawing // Load the shader to be used for 2d drawing
const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; const char* shaderFilepath = "Shaders/SimpleTextured.azshader";
AZ::Data::Instance<AZ::RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath); AZ::Data::Instance<AZ::RPI::Shader> shader = AZ::RPI::LoadCriticalShader(shaderFilepath);
// Set scene to be associated with the dynamic draw context // Set scene to be associated with the dynamic draw context
AZ::RPI::ScenePtr scene; AZ::RPI::ScenePtr scene;

@ -58,7 +58,7 @@ void UiRenderer::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstra
// Load the UI shader // Load the UI shader
const char* uiShaderFilepath = "Shaders/LyShineUI.azshader"; const char* uiShaderFilepath = "Shaders/LyShineUI.azshader";
AZ::Data::Instance<AZ::RPI::Shader> uiShader = AZ::RPI::LoadShader(uiShaderFilepath); AZ::Data::Instance<AZ::RPI::Shader> uiShader = AZ::RPI::LoadCriticalShader(uiShaderFilepath);
// Create scene to be used by the dynamic draw context // Create scene to be used by the dynamic draw context
if (m_viewportContext) if (m_viewportContext)

Loading…
Cancel
Save