Files
o3de/Gems/Atom/RHI/Metal/Code/Source/RHI.Builders/ShaderPlatformInterface.h
Steve Pham 38261d0800 Shorten copyright headers by splitting into 2 lines (#2213)
* Updated all copyright headers to split the longer original copyright line into 2 shorter lines

Signed-off-by: Steve Pham <spham@amazon.com>
2021-07-16 15:25:48 -07:00

175 lines
8.4 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
*
*/
#pragma once
#include <Atom/RHI.Edit/ShaderPlatformInterface.h>
#include <Atom/RHI.Reflect/Metal/Base.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
namespace Metal
{
class ShaderPlatformInterface :
public RHI::ShaderPlatformInterface
{
public:
explicit ShaderPlatformInterface(uint32_t apiUniqueIndex);
RHI::APIType GetAPIType() const override;
AZ::Name GetAPIName() const override;
RHI::Ptr<RHI::ShaderStageFunction> CreateShaderStageFunction(
const StageDescriptor& stageDescriptor) override;
bool IsShaderStageForRaster(RHI::ShaderHardwareStage shaderStageType) const override;
bool IsShaderStageForCompute(RHI::ShaderHardwareStage shaderStageType) const override;
bool IsShaderStageForRayTracing(RHI::ShaderHardwareStage shaderStageType) const override;
RHI::Ptr<RHI::PipelineLayoutDescriptor> CreatePipelineLayoutDescriptor() override;
bool BuildPipelineLayoutDescriptor(
RHI::Ptr<RHI::PipelineLayoutDescriptor> pipelineLayoutDescriptor,
const ShaderResourceGroupInfoList& srgInfoList,
const RootConstantsInfo& rootConstantsInfo,
const RHI::ShaderCompilerArguments& shaderCompilerArguments) override;
bool VariantCompilationRequiresSrgLayoutData() const override { return true; }
bool CompilePlatformInternal(
const AssetBuilderSDK::PlatformInfo& platform,
const AZStd::string& shaderSourcePath,
const AZStd::string& functionName,
RHI::ShaderHardwareStage shaderStage,
const AZStd::string& tempFolderPath,
StageDescriptor& outputDescriptor,
const RHI::ShaderCompilerArguments& shaderCompilerArguments) const override;
AZStd::string GetAzslCompilerParameters(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const;
AZStd::string GetAzslCompilerWarningParameters(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const;
bool BuildHasDebugInfo(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const override;
const char* GetAzslHeader(const AssetBuilderSDK::PlatformInfo& platform) const override;
private:
ShaderPlatformInterface() = delete;
bool CompileHLSLShader(
const AZStd::string& shaderSourceFile,
const AZStd::string& tempFolder,
const AZStd::string& entryPoint,
const RHI::ShaderHardwareStage shaderAssetType,
const RHI::ShaderCompilerArguments& shaderCompilerArguments,
AZStd::vector<char>& compiledShader,
AZStd::vector<uint8_t>& compiledByteCode,
const AssetBuilderSDK::PlatformInfo& platform,
ByProducts& byproducts) const;
bool UpdateCompiledShader(AZ::IO::FileIOStream& fileStream,
const char* platformName,
const char* fileName,
AZStd::vector<char>& compiledShader) const;
bool CreateMetalLib(const char* platformName,
const AZStd::string& shaderSourceFile,
const AZStd::string& tempFolder,
AZStd::vector<uint8_t>& compiledByteCode,
AZStd::vector<char>& sourceMetalShader,
const AssetBuilderSDK::PlatformInfo& platform) const;
using ArgBufferEntries = AZStd::pair<AZStd::string, uint32_t>;
struct compareByRegisterId {
bool operator()(const ArgBufferEntries& lhs, const ArgBufferEntries& rhs)
{
return lhs.second < rhs.second;
}
};
/**
* These set of functions will parse the final metal source code and add unused variables
* within the declaration of argument buffers so that they match ShaderResourceGroupLayout
* This is necessary because metal drivers expect the argbuffer layout bound at runtime to match
* the one declared in the shaders or we get undefined behaviour (hard crashes/weird lags/etc).
*
* For example - Given SRG like so
* ShaderResourceGroup ObjectSrg : SRG_PerObject
* {
* Texture2D<float4> FontImage;
*
* Sampler LinearSampler
* {
* MinFilter = Linear;
* MagFilter = Linear;
* MipFilter = Linear;
* AddressU = Clamp;
* AddressV = Clamp;
* AddressW = Clamp;
* };
*
* column_major float4x4 m_projectionMatrix;
* }
*
* the imgui vertex shader that only uses m_projectionMatrix will modify the following metal shader
*
* struct spvDescriptorSetBuffer0
* {
* constant type_ConstantBuffer_PerObject_SRGConstantsStruct* PerObject_SRGConstantBuffer [[id(2)]];
* };
*
* to
*
* struct spvDescriptorSetBuffer0
* {
* texture2d<float> dummyImage0 [[id(0)]];
* sampler dummySampler1 [[id(1)]];
* constant type_ConstantBuffer_PerObject_SRGConstantsStruct* PerObject_SRGConstantBuffer [[id(2)]];
* };
*/
bool AddUnusedResources(AZStd::vector<char>& compiledShader) const;
//Insert all the static sampler resource string entries into a set.
bool AddSamplerEntries(const RHI::ShaderResourceGroupLayout& groupLayout,
AZStd::string& argBufferStr) const;
//! Insert all the image resource string entries into the set. Use ProcessSamplerEntry as a helper method.
bool AddImageEntries(const RHI::ShaderResourceGroupLayout& groupLayout,
AZStd::string& argBufferStr) const;
bool ProcessSamplerEntry(uint32_t regId, AZStd::string& argBufferStr, uint32_t samplercount) const;
//! Insert all the constant buffer resource string entries into the set.
bool AddConstantBufferEntries(const RHI::ShaderResourceGroupLayout& groupLayout,
AZStd::string& constantBufferTempStructs,
AZStd::string& argBufferStr,
uint32_t groupLayoutIndex) const;
//! Insert all the buffer resource string entries into the set.
bool AddBufferEntries(const RHI::ShaderResourceGroupLayout& groupLayout,
AZStd::string& structuredBufferTempStructs,
AZStd::string& argBufferStr,
uint32_t groupLayoutIndex) const;
//! Helper function to add already existing resource entry into the set
bool AddExistingResourceEntry(const char* resourceStr,
size_t resourceStartPos,
uint32_t regId,
AZStd::string& argBufferStr) const;
//! This is to cache the srg layout which is needed to add the unused variables
mutable AZStd::fixed_vector<const RHI::ShaderResourceGroupLayout*, RHI::Limits::Pipeline::ShaderResourceGroupCountMax> m_srgLayouts;
//! The set helps remove duplicates and keeps the entries sorted based on register id
mutable AZStd::set<ArgBufferEntries, compareByRegisterId> m_argBufferEntries;
const Name m_apiName{APINameString};
};
}
}