[ATOM-15978] ShaderVariantAssetBuilder needs to fill up ShaderPlatformInterface::m_srgLayouts for Metal (#2156)

ShaderVariantAssetBuilder builds SRG Layout data only for Metal.

Signed-off-by: garrieta <garrieta@amazon.com>
This commit is contained in:
galibzon
2021-07-14 15:38:08 -05:00
committed by GitHub
parent e32b7a7c87
commit 32a2796620
5 changed files with 151 additions and 2 deletions
@@ -95,7 +95,7 @@ namespace AZ
shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder";
// Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update
// ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder".
shaderVariantAssetBuilderDescriptor.m_version = 23; // ATOM-15472
shaderVariantAssetBuilderDescriptor.m_version = 24; // ATOM-15978
shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>();
shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
@@ -48,6 +48,7 @@
#include "ShaderAssetBuilder.h"
#include "ShaderBuilderUtility.h"
#include "SrgLayoutUtility.h"
#include "AzslData.h"
#include "AzslCompiler.h"
#include <CommonFiles/Preprocessor.h>
@@ -520,6 +521,96 @@ namespace AZ
return;
}
}
static bool LoadSrgLayoutListFromShaderAssetBuilder(
const RHI::ShaderPlatformInterface* shaderPlatformInterface,
const AssetBuilderSDK::PlatformInfo& platformInfo,
const AzslCompiler& azslCompiler, const AZStd::string& shaderSourceFileFullPath,
const RPI::SupervariantIndex supervariantIndex,
const bool platformUsesRegisterSpaces,
RPI::ShaderResourceGroupLayoutList& srgLayoutList,
RootConstantData& rootConstantData)
{
auto srgJsonPathOutcome = ShaderBuilderUtility::ObtainBuildArtifactPathFromShaderAssetBuilder(
shaderPlatformInterface->GetAPIUniqueIndex(), platformInfo.m_identifier, shaderSourceFileFullPath, supervariantIndex.GetIndex(), AZ::RPI::ShaderAssetSubId::SrgJson);
if (!srgJsonPathOutcome.IsSuccess())
{
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", srgJsonPathOutcome.GetError().c_str());
return false;
}
auto srgJsonPath = srgJsonPathOutcome.TakeValue();
auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath);
if (!jsonOutcome.IsSuccess())
{
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str());
return false;
}
SrgDataContainer srgData;
if (!azslCompiler.ParseSrgPopulateSrgData(jsonOutcome.GetValue(), srgData))
{
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to parse srg data");
return false;
}
// Add all Shader Resource Group Assets that were defined in the shader code to the shader asset
if (!SrgLayoutUtility::LoadShaderResourceGroupLayouts(ShaderVariantAssetBuilderName, srgData, platformUsesRegisterSpaces, srgLayoutList))
{
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to load ShaderResourceGroupLayouts");
return false;
}
for (auto srgLayout : srgLayoutList)
{
if (!srgLayout->Finalize())
{
AZ_Error(ShaderVariantAssetBuilderName, false,
"Failed to finalize SrgLayout %s", srgLayout->GetName().GetCStr());
return false;
}
}
// Access the root constants reflection
if (!azslCompiler.ParseSrgPopulateRootConstantData(
jsonOutcome.GetValue(),
rootConstantData)) // consuming data from --srg ("InlineConstantBuffer" subjson section)
{
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to obtain root constant data reflection");
return false;
}
return true;
}
static bool LoadBindingDependenciesFromShaderAssetBuilder(
const RHI::ShaderPlatformInterface* shaderPlatformInterface,
const AssetBuilderSDK::PlatformInfo& platformInfo,
const AzslCompiler& azslCompiler, const AZStd::string& shaderSourceFileFullPath,
const RPI::SupervariantIndex supervariantIndex,
BindingDependencies& bindingDependencies)
{
auto bindingsJsonPathOutcome = ShaderBuilderUtility::ObtainBuildArtifactPathFromShaderAssetBuilder(
shaderPlatformInterface->GetAPIUniqueIndex(), platformInfo.m_identifier, shaderSourceFileFullPath, supervariantIndex.GetIndex(), AZ::RPI::ShaderAssetSubId::BindingdepJson);
if (!bindingsJsonPathOutcome.IsSuccess())
{
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", bindingsJsonPathOutcome.GetError().c_str());
return false;
}
auto bindingsJsonPath = bindingsJsonPathOutcome.TakeValue();
auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath);
if (!jsonOutcome.IsSuccess())
{
AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str());
return false;
}
if (!azslCompiler.ParseBindingdepPopulateBindingDependencies(jsonOutcome.GetValue(), bindingDependencies))
{
AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to parse binding dependencies data");
return false;
}
return true;
}
// Returns the content of the hlsl file for the given supervariant as produced by ShaderAsssetBuilder.
@@ -773,6 +864,50 @@ namespace AZ
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
return;
}
//! It is important to keep this refcounted pointer outside of the if block to prevent it from being destroyed.
RHI::Ptr<RHI::PipelineLayoutDescriptor> pipelineLayoutDescriptor;
if (shaderPlatformInterface->VariantCompilationRequiresSrgLayoutData())
{
AZStd::string azslcCompilerParameters =
shaderPlatformInterface->GetAzslCompilerParameters(buildOptions.m_compilerArguments);
const bool platformUsesRegisterSpaces =
(AzFramework::StringFunc::Find(azslcCompilerParameters, "--use-spaces") != AZStd::string::npos);
RPI::ShaderResourceGroupLayoutList srgLayoutList;
RootConstantData rootConstantData;
if (!LoadSrgLayoutListFromShaderAssetBuilder(
shaderPlatformInterface, request.m_platformInfo, azslc, shaderSourceFileFullPath, supervariantIndex,
platformUsesRegisterSpaces,
srgLayoutList,
rootConstantData))
{
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
return;
}
BindingDependencies bindingDependencies;
if (!LoadBindingDependenciesFromShaderAssetBuilder(
shaderPlatformInterface, request.m_platformInfo, azslc, shaderSourceFileFullPath, supervariantIndex,
bindingDependencies))
{
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
return;
}
pipelineLayoutDescriptor =
ShaderBuilderUtility::BuildPipelineLayoutDescriptorForApi(
ShaderVariantAssetBuilderName, srgLayoutList, shaderEntryPoints, buildOptions.m_compilerArguments, rootConstantData,
shaderPlatformInterface, bindingDependencies);
if (!pipelineLayoutDescriptor)
{
AZ_Error(
ShaderVariantAssetBuilderName, false, "Failed to build pipeline layout descriptor for api=[%s]",
shaderPlatformInterface->GetAPIName().GetCStr());
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
return;
}
}
// Setup the shader variant creation context:
ShaderVariantCreationContext shaderVariantCreationContext =
@@ -144,6 +144,12 @@ namespace AZ
const ShaderResourceGroupInfoList& srgInfoList,
const RootConstantsInfo& rootConstantsInfo,
const ShaderCompilerArguments& shaderCompilerArguments) = 0;
//! In general, shader compilation doesn't require SRG Layout data, but RHIs like
//! Metal don't do well if unused resources (descriptors) are not bound. If this function returns TRUE
//! the ShaderVariantAssetBuilder will invoke BuildPipelineLayoutDescriptor() so the RHI gets the chance to
//! build SRG Layout data which will be useful when compiling MetalISL to Metal byte code.
virtual bool VariantCompilationRequiresSrgLayoutData() const { return false; }
//! See AZ::RHI::Factory::GetAPIUniqueIndex() for details.
//! See AZ::RHI::Limits::APIType::PerPlatformApiUniqueIndexMax.
@@ -159,7 +159,13 @@ namespace AZ
arguments += " -Zi"; // Generate debug information
arguments += " -Zss"; // Compute Shader Hash considering source information
}
arguments += " " + m_dxcAdditionalFreeArguments;
// strip spaces at both sides
AZStd::string dxcAdditionalFreeArguments = m_dxcAdditionalFreeArguments;
AzFramework::StringFunc::TrimWhiteSpace(dxcAdditionalFreeArguments, true, true);
if (!dxcAdditionalFreeArguments.empty())
{
arguments += " " + dxcAdditionalFreeArguments;
}
return arguments;
}
}
@@ -40,6 +40,8 @@ namespace AZ
const ShaderResourceGroupInfoList& srgInfoList,
const RootConstantsInfo& rootConstantsInfo,
const RHI::ShaderCompilerArguments& shaderCompilerArguments) override;
bool VariantCompilationRequiresSrgLayoutData() const override { return true; }
bool CompilePlatformInternal(
const AssetBuilderSDK::PlatformInfo& platform,