Files
o3de/Gems/Atom/RPI/Code/Source/RPI.Edit/Shader/ShaderSourceData.cpp
T
Jeremy Ong 743ade1765 Add "Definitions" field to shader asset
Shaders can now specify a top-level field "Definitions" which
accepts an array of string values. Each string will be appended
to the set of preprocessor definitions defined globally and forwarded
to the MCPP preprocessor on shader build. The shader-reload soak test
was modified to accept a new shader to test this feature in the ASV.

Signed-off-by: Jeremy Ong <jcong@amazon.com>
2022-02-02 00:23:55 -07:00

170 lines
7.5 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
#include <Atom/RHI.Edit/Utils.h>
#include <Atom/RHI.Edit/ShaderCompilerArguments.h>
#include <AzCore/std/string/regex.h>
#include <AzFramework/StringFunc/StringFunc.h>
namespace AZ
{
namespace RPI
{
void ShaderSourceData::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<ShaderSourceData>()
->Version(5)
->Field("Source", &ShaderSourceData::m_source)
->Field("DrawList", &ShaderSourceData::m_drawListName)
->Field("DepthStencilState", &ShaderSourceData::m_depthStencilState)
->Field("RasterState", &ShaderSourceData::m_rasterState)
->Field("BlendState", &ShaderSourceData::m_blendState)
->Field("ProgramSettings", &ShaderSourceData::m_programSettings)
->Field("Definitions", &ShaderSourceData::m_definitions)
->Field("CompilerHints", &ShaderSourceData::m_compiler)
->Field("DisabledRHIBackends", &ShaderSourceData::m_disabledRhiBackends)
->Field("Supervariants", &ShaderSourceData::m_supervariants)
;
serializeContext->Class<ShaderSourceData::ProgramSettings>()
->Version(1)
->Field("EntryPoints", &ProgramSettings::m_entryPoints)
;
serializeContext->Class<ShaderSourceData::EntryPoint>()
->Version(1)
->Field("Name", &EntryPoint::m_name)
->Field("Type", &EntryPoint::m_type)
;
serializeContext->Class<ShaderSourceData::SupervariantInfo>()
->Version(1)
->Field("Name", &SupervariantInfo::m_name)
->Field("PlusArguments", &SupervariantInfo::m_plusArguments)
->Field("MinusArguments", &SupervariantInfo::m_minusArguments);
}
}
bool ShaderSourceData::IsRhiBackendDisabled(const AZ::Name& rhiName) const
{
return AZStd::any_of(AZ_BEGIN_END(m_disabledRhiBackends), [&](const AZStd::string& currentRhiName)
{
return currentRhiName == rhiName.GetStringView();
});
}
//! Helper function.
//! Parses a string of command line arguments looking for c-preprocessor macro definitions and appends the name of macro definition arguments.
//! Example:
//! Input string: "--switch1 -DMACRO1 -v -DMACRO2=23"
//! append the following items: ["MACRO1", "MACRO2"]
static void GetListOfMacroDefinitionNames(
const AZStd::string& stringWithArguments, AZStd::vector<AZStd::string>& macroDefinitionNames)
{
const AZStd::regex macroRegex(R"(-D\s*(\w+))", AZStd::regex::ECMAScript);
AZStd::string hayStack(stringWithArguments);
AZStd::smatch match;
while (AZStd::regex_search(hayStack.c_str(), match, macroRegex))
{
// First pattern is always the entire string
for (unsigned i = 1; i < match.size(); ++i)
{
if (match[i].matched)
{
AZStd::string macroToAdd(match[i].str().c_str());
const bool isPresent = AZStd::any_of(AZ_BEGIN_END(macroDefinitionNames),
[&](AZStd::string_view macroName) -> bool
{
return macroToAdd == macroName;
}
);
if (isPresent)
{
continue;
}
macroDefinitionNames.push_back(macroToAdd);
}
}
hayStack = match.suffix();
}
}
AZStd::vector<AZStd::string> ShaderSourceData::SupervariantInfo::GetCombinedListOfMacroDefinitionNamesToRemove() const
{
AZStd::vector<AZStd::string> macroDefinitionNames;
GetListOfMacroDefinitionNames(m_minusArguments, macroDefinitionNames);
GetListOfMacroDefinitionNames(m_plusArguments, macroDefinitionNames);
return macroDefinitionNames;
}
//! Helper function.
//! Parses a string of command line arguments looking for c-preprocessor macro definitions and appends macro definition
//! arguments. Example: Input string: "--switch1 -DMACRO1 -v -DMACRO2=23" append the following items: ["MACRO1", "MACRO2=23"]
static void GetListOfMacroDefinitions(
const AZStd::string& stringWithArguments, AZStd::vector<AZStd::string>& macroDefinitions)
{
const AZStd::regex macroRegex(R"(-D\s*(\w+)(=\w+)?)", AZStd::regex::ECMAScript);
AZStd::string hayStack(stringWithArguments);
AZStd::smatch match;
while (AZStd::regex_search(hayStack.c_str(), match, macroRegex))
{
if (match.size() > 1)
{
AZStd::string macro(match[1].str().c_str());
if (match.size() > 2)
{
macro += match[2].str().c_str();
}
macroDefinitions.push_back(macro);
}
hayStack = match.suffix();
}
}
AZStd::vector<AZStd::string> ShaderSourceData::SupervariantInfo::GetMacroDefinitionsToAdd() const
{
AZStd::vector<AZStd::string> parsedMacroDefinitions;
GetListOfMacroDefinitions(m_plusArguments, parsedMacroDefinitions);
return parsedMacroDefinitions;
}
AZStd::string ShaderSourceData::SupervariantInfo::GetCustomizedArgumentsForAzslc(
const AZStd::string& initialAzslcCompilerArguments) const
{
const AZStd::regex macroRegex(R"(-D\s*(\w+(=\S+)?))", AZStd::regex::ECMAScript);
// We are only concerned with AZSLc arguments. Let's remove the C-Preprocessor macro definitions
// from @minusArguments.
const AZStd::string minusArguments = AZStd::regex_replace(m_minusArguments, macroRegex, "");
const AZStd::string plusArguments = AZStd::regex_replace(m_plusArguments, macroRegex, "");
AZStd::string azslcArgumentsToRemove = minusArguments + " " + plusArguments;
AZStd::vector<AZStd::string> azslcArgumentNamesToRemove = RHI::CommandLineArgumentUtils::GetListOfArgumentNames(azslcArgumentsToRemove);
// At this moment @azslcArgumentsToRemove contains arguments for AZSLc that can be of the form:
// -<arg>
// --<arg>[=<value>]
// We need to remove those from @initialAzslcCompilerArguments.
AZStd::string customizedArguments = RHI::CommandLineArgumentUtils::RemoveArgumentsFromCommandLineString(
azslcArgumentNamesToRemove, initialAzslcCompilerArguments);
customizedArguments += " " + plusArguments;
return RHI::CommandLineArgumentUtils::RemoveExtraSpaces(customizedArguments);
}
} // namespace RPI
} // namespace AZ