You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb Mihnea.Balta, Will.Damon, Dmitriy.Dyomin #fyi Rolando.Caloca, Brian.White #jira none #rnx [CL 15225002 by Lukas Hermanns in ue5-main branch]
595 lines
23 KiB
C++
595 lines
23 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "HlslccHeaderWriter.h"
|
|
#include "ShaderConductorContext.h"
|
|
|
|
THIRD_PARTY_INCLUDES_START
|
|
#include "spirv_reflect.h"
|
|
THIRD_PARTY_INCLUDES_END
|
|
|
|
|
|
namespace CrossCompiler
|
|
{
|
|
|
|
template <typename FmtType, typename... Types>
|
|
static void MetaDataPrintf(FString& MetaData, const FmtType& Fmt, Types... Args)
|
|
{
|
|
if (!MetaData.IsEmpty())
|
|
{
|
|
MetaData += TEXT(",");
|
|
}
|
|
MetaData += FString::Printf(Fmt, Args...);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteInputAttribute(const SpvReflectInterfaceVariable& Attribute)
|
|
{
|
|
WriteIOAttribute(Strings.InputAttributes, Attribute, /*bIsInput:*/ true);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteInputAttribute(const TCHAR* AttributeName, const TCHAR* TypeSpecifier, int32 Location, bool bLocationPrefix, bool bLocationSuffix)
|
|
{
|
|
WriteIOAttribute(Strings.InputAttributes, AttributeName, TypeSpecifier, Location, bLocationPrefix, bLocationSuffix);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteOutputAttribute(const SpvReflectInterfaceVariable& Attribute)
|
|
{
|
|
WriteIOAttribute(Strings.OutputAttributes, Attribute, /*bIsInput:*/ false);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteOutputAttribute(const TCHAR* AttributeName, const TCHAR* TypeSpecifier, int32 Location, bool bLocationPrefix, bool bLocationSuffix)
|
|
{
|
|
WriteIOAttribute(Strings.OutputAttributes, AttributeName, TypeSpecifier, Location, bLocationPrefix, bLocationSuffix);
|
|
}
|
|
|
|
static void ConvertMetaDataTypeSpecifierPrimary(const SpvReflectTypeDescription& TypeSpecifier, FString& OutTypeName, uint32& OutTypeBitWidth, bool bBaseTypeOnly)
|
|
{
|
|
// Generate prefix for base type
|
|
if (TypeSpecifier.type_flags & SPV_REFLECT_TYPE_FLAG_BOOL)
|
|
{
|
|
OutTypeName += TEXT('b');
|
|
OutTypeBitWidth = 8;
|
|
}
|
|
else if (TypeSpecifier.type_flags & SPV_REFLECT_TYPE_FLAG_INT)
|
|
{
|
|
if (TypeSpecifier.traits.numeric.scalar.signedness)
|
|
{
|
|
OutTypeName += TEXT('i');
|
|
}
|
|
else
|
|
{
|
|
OutTypeName += TEXT('u');
|
|
}
|
|
OutTypeBitWidth = 32;
|
|
}
|
|
else if (TypeSpecifier.type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT)
|
|
{
|
|
if (TypeSpecifier.traits.numeric.scalar.width == 16)
|
|
{
|
|
OutTypeName += TEXT('h');
|
|
OutTypeBitWidth = 16;
|
|
}
|
|
else
|
|
{
|
|
OutTypeName += TEXT('f');
|
|
OutTypeBitWidth = 32;
|
|
}
|
|
}
|
|
|
|
if (!bBaseTypeOnly)
|
|
{
|
|
// Generate number for vector size
|
|
const SpvReflectTypeFlags SpvScalarTypeFlags = (SPV_REFLECT_TYPE_FLAG_BOOL | SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_FLOAT);
|
|
if (TypeSpecifier.type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR)
|
|
{
|
|
static const TCHAR* VectorDims = TEXT("1234");
|
|
const uint32 VectorSize = TypeSpecifier.traits.numeric.vector.component_count;
|
|
check(VectorSize >= 1 && VectorSize <= 4);
|
|
OutTypeName += VectorDims[VectorSize - 1];
|
|
}
|
|
else if (TypeSpecifier.type_flags & SPV_REFLECT_TYPE_FLAG_MATRIX)
|
|
{
|
|
//TODO
|
|
}
|
|
else if ((TypeSpecifier.type_flags & SpvScalarTypeFlags) != 0)
|
|
{
|
|
OutTypeName += TEXT('1'); // add single scalar component
|
|
}
|
|
}
|
|
}
|
|
|
|
static FString ConvertMetaDataTypeSpecifier(const SpvReflectTypeDescription& TypeSpecifier, uint32* OutTypeBitWidth = nullptr, bool bBaseTypeOnly = false)
|
|
{
|
|
FString TypeName;
|
|
uint32 TypeBitWidth = sizeof(float) * 8;
|
|
ConvertMetaDataTypeSpecifierPrimary(TypeSpecifier, TypeName, TypeBitWidth, bBaseTypeOnly);
|
|
if (OutTypeBitWidth)
|
|
{
|
|
*OutTypeBitWidth = TypeBitWidth;
|
|
}
|
|
return TypeName;
|
|
}
|
|
|
|
static const TCHAR* SpvBuiltinToString(const SpvBuiltIn BuiltIn)
|
|
{
|
|
switch (BuiltIn)
|
|
{
|
|
case SpvBuiltInPosition: return TEXT("gl_Position");
|
|
case SpvBuiltInPointSize: return TEXT("gl_PointSize");
|
|
case SpvBuiltInClipDistance: return TEXT("gl_ClipDistance");
|
|
case SpvBuiltInCullDistance: return TEXT("gl_CullDistance");
|
|
case SpvBuiltInVertexId: return TEXT("gl_VertexID");
|
|
case SpvBuiltInInstanceId: return TEXT("gl_InstanceID");
|
|
case SpvBuiltInPrimitiveId: return TEXT("gl_PrimitiveID");
|
|
case SpvBuiltInInvocationId: return TEXT("gl_InvocationID");
|
|
case SpvBuiltInLayer: return TEXT("gl_Layer");
|
|
case SpvBuiltInViewportIndex: return TEXT("gl_ViewportIndex");
|
|
case SpvBuiltInTessLevelOuter: return TEXT("gl_TessLevelOuter");
|
|
case SpvBuiltInTessLevelInner: return TEXT("gl_TessLevelInner");
|
|
case SpvBuiltInTessCoord: return TEXT("gl_TessCoord");
|
|
case SpvBuiltInPatchVertices: return TEXT("gl_PatchVertices");
|
|
case SpvBuiltInFragCoord: return TEXT("gl_FragCoord");
|
|
case SpvBuiltInPointCoord: return TEXT("gl_PointCoord");
|
|
case SpvBuiltInFrontFacing: return TEXT("gl_FrontFacing");
|
|
case SpvBuiltInSampleId: return TEXT("gl_SampleID");
|
|
case SpvBuiltInSamplePosition: return TEXT("gl_SamplePosition");
|
|
case SpvBuiltInSampleMask: return TEXT("gl_SampleMask");
|
|
case SpvBuiltInFragDepth: return TEXT("gl_FragDepth");
|
|
case SpvBuiltInHelperInvocation: return TEXT("gl_HelperInvocation");
|
|
case SpvBuiltInNumWorkgroups: return TEXT("gl_NumWorkgroups");
|
|
case SpvBuiltInWorkgroupSize: return TEXT("gl_WorkgroupSize");
|
|
case SpvBuiltInWorkgroupId: return TEXT("gl_WorkgroupID");
|
|
case SpvBuiltInLocalInvocationId: return TEXT("gl_LocalInvocationID");
|
|
case SpvBuiltInGlobalInvocationId: return TEXT("gl_GlobalInvocationID");
|
|
case SpvBuiltInLocalInvocationIndex: return TEXT("gl_LocalInvocationIndex");
|
|
case SpvBuiltInWorkDim: return TEXT("gl_WorkDim");
|
|
case SpvBuiltInGlobalSize: return TEXT("gl_GlobalSize");
|
|
case SpvBuiltInEnqueuedWorkgroupSize: return TEXT("gl_EnqueuedWorkgroupSize");
|
|
case SpvBuiltInGlobalOffset: return TEXT("gl_GlobalOffset");
|
|
case SpvBuiltInGlobalLinearId: return TEXT("gl_GlobalLinearID");
|
|
case SpvBuiltInSubgroupSize: return TEXT("gl_SubgroupSize");
|
|
case SpvBuiltInSubgroupMaxSize: return TEXT("gl_SubgroupMaxSize");
|
|
case SpvBuiltInNumSubgroups: return TEXT("gl_NumSubgroups");
|
|
case SpvBuiltInNumEnqueuedSubgroups: return TEXT("gl_NumEnqueuedSubgroups");
|
|
case SpvBuiltInSubgroupId: return TEXT("gl_SubgroupID");
|
|
case SpvBuiltInSubgroupLocalInvocationId: return TEXT("gl_SubgroupLocalInvocationID");
|
|
case SpvBuiltInVertexIndex: return TEXT("gl_VertexIndex");
|
|
case SpvBuiltInInstanceIndex: return TEXT("gl_InstanceIndex");
|
|
case SpvBuiltInSubgroupEqMask: return TEXT("gl_SubgroupEqMask");
|
|
case SpvBuiltInSubgroupGeMask: return TEXT("gl_SubgroupGeMask");
|
|
case SpvBuiltInSubgroupGtMask: return TEXT("gl_SubgroupGtMask");
|
|
case SpvBuiltInSubgroupLeMask: return TEXT("gl_SubgroupLeMask");
|
|
case SpvBuiltInSubgroupLtMask: return TEXT("gl_SubgroupLtMask");
|
|
case SpvBuiltInBaseVertex: return TEXT("gl_BaseVertex");
|
|
case SpvBuiltInBaseInstance: return TEXT("gl_BaseInstance");
|
|
case SpvBuiltInDrawIndex: return TEXT("gl_DrawIndex");
|
|
case SpvBuiltInDeviceIndex: return TEXT("gl_DeviceIndex");
|
|
case SpvBuiltInViewIndex: return TEXT("gl_ViewIndex");
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
static FString ConvertAttributeToMetaDataSemantic(const ANSICHAR* AttributeName, const SpvBuiltIn BuiltIn, bool bIsInput)
|
|
{
|
|
if (const TCHAR* BuiltInName = SpvBuiltinToString(BuiltIn))
|
|
{
|
|
return FString(BuiltInName);
|
|
}
|
|
else
|
|
{
|
|
check(AttributeName != nullptr && *AttributeName != '\0');
|
|
FString InSemantic = ANSI_TO_TCHAR(AttributeName);
|
|
FString OutSemantic = (bIsInput ? TEXT("in_") : TEXT("out_"));
|
|
|
|
if (InSemantic.StartsWith(TEXT("SV_")))
|
|
{
|
|
OutSemantic += InSemantic.Right(InSemantic.Len() - 3);
|
|
}
|
|
else
|
|
{
|
|
OutSemantic += InSemantic;
|
|
}
|
|
|
|
return OutSemantic;
|
|
}
|
|
}
|
|
|
|
// Flattens the array dimensions of the interface variable (aka shader attribute), e.g. from float4[2][3] -> float4[6]
|
|
static uint32 FlattenAttributeArrayDimension(const SpvReflectInterfaceVariable& Attribute, uint32 FirstArrayDim = 0)
|
|
{
|
|
uint32 FlattenedArrayDim = 1;
|
|
for (uint32 ArrayDimIndex = FirstArrayDim; ArrayDimIndex < Attribute.array.dims_count; ++ArrayDimIndex)
|
|
{
|
|
FlattenedArrayDim *= Attribute.array.dims[ArrayDimIndex];
|
|
}
|
|
return FlattenedArrayDim;
|
|
}
|
|
|
|
// Returns the string position where the index in the specified HLSL semantic beings, e.g. "SV_Target2" -> 9, "SV_Target" -> INDEX_NONE
|
|
static int32 FindIndexInHlslSemantic(const FString& Semantic)
|
|
{
|
|
int32 Index = Semantic.Len();
|
|
if (Index > 0 && FChar::IsDigit(Semantic[Index - 1]))
|
|
{
|
|
while (Index > 0 && FChar::IsDigit(Semantic[Index - 1]))
|
|
{
|
|
--Index;
|
|
}
|
|
return Index;
|
|
}
|
|
return INDEX_NONE;
|
|
}
|
|
|
|
// private
|
|
void FHlslccHeaderWriter::WriteIOAttribute(FString& OutMetaData, const TCHAR* AttributeName, const TCHAR* TypeSpecifier, int32 Location, bool bLocationPrefix, bool bLocationSuffix)
|
|
{
|
|
MetaDataPrintf(OutMetaData, TEXT("%s"), TypeSpecifier);
|
|
if (bLocationPrefix)
|
|
{
|
|
OutMetaData += FString::Printf(TEXT(";%d:"), Location);
|
|
}
|
|
else
|
|
{
|
|
OutMetaData += TEXT(":");
|
|
}
|
|
if (bLocationSuffix)
|
|
{
|
|
OutMetaData += FString::Printf(TEXT("%s%d"), AttributeName, Location);
|
|
}
|
|
else
|
|
{
|
|
OutMetaData += AttributeName;
|
|
}
|
|
}
|
|
|
|
// private
|
|
void FHlslccHeaderWriter::WriteIOAttribute(FString& OutMetaData, const SpvReflectInterfaceVariable& Attribute, bool bIsInput)
|
|
{
|
|
// Ignore interface variables that are only generated for intermediate results
|
|
if (CrossCompiler::FShaderConductorContext::IsIntermediateSpirvOutputVariable(Attribute.name))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FString TypeSpecifier = ConvertMetaDataTypeSpecifier(*Attribute.type_description);
|
|
FString Semantic = ConvertAttributeToMetaDataSemantic(Attribute.semantic, Attribute.built_in, bIsInput);
|
|
|
|
if (Attribute.array.dims_count > 0)
|
|
{
|
|
// Get semantic without index, e.g. "out_Target0" -> "out_Target"
|
|
const int32 SemanticIndexPos = FindIndexInHlslSemantic(Semantic);
|
|
if (SemanticIndexPos != INDEX_NONE)
|
|
{
|
|
Semantic = Semantic.Left(SemanticIndexPos);
|
|
}
|
|
|
|
if (Attribute.location == -1)
|
|
{
|
|
// Flatten array dimensions, e.g. from float4[3][2] -> float4[6]
|
|
const uint32 FlattenedArrayDim = FlattenAttributeArrayDimension(Attribute);
|
|
|
|
// Emit one output slot for each array element, e.g. "out float4 OutColor[2] : SV_Target0" occupies output slot SV_Target0 and SV_Target1.
|
|
for (uint32 FlattenedArrayIndex = 0; FlattenedArrayIndex < FlattenedArrayDim; ++FlattenedArrayIndex)
|
|
{
|
|
// If there is no binding slot, emit output as system value array such as "gl_SampleMask[]"
|
|
MetaDataPrintf(
|
|
OutMetaData,
|
|
TEXT("%s;%d:%s[%d]"),
|
|
*TypeSpecifier, // type specifier
|
|
Attribute.location,
|
|
*Semantic,
|
|
FlattenedArrayIndex
|
|
);
|
|
}
|
|
}
|
|
else if (!bIsInput)
|
|
{
|
|
//NOTE: For some reason, the meta data for output slot arrays must be entirely flattened, including the outer most array dimension
|
|
// Flatten array dimensions, e.g. from float4[3][2] -> float4[6]
|
|
const uint32 FlattenedArrayDim = FlattenAttributeArrayDimension(Attribute);
|
|
|
|
// Emit one output slot for each array element, e.g. "out float4 OutColor[2] : SV_Target0" occupies output slot SV_Target0 and SV_Target1.
|
|
for (uint32 FlattenedArrayIndex = 0; FlattenedArrayIndex < FlattenedArrayDim; ++FlattenedArrayIndex)
|
|
{
|
|
const uint32 BindingSlot = Attribute.location + FlattenedArrayIndex;
|
|
MetaDataPrintf(
|
|
OutMetaData,
|
|
TEXT("%s;%d:%s%d"),
|
|
*TypeSpecifier, // Type specifier
|
|
BindingSlot,
|
|
*Semantic,
|
|
BindingSlot
|
|
);
|
|
}
|
|
}
|
|
else if (Attribute.array.dims_count >= 2)
|
|
{
|
|
// Flatten array dimensions, e.g. from float4[3][2] -> float4[6]
|
|
const uint32 FlattenedArrayDim = FlattenAttributeArrayDimension(Attribute, 1);
|
|
|
|
// Emit one output slot for each array element, e.g. "out float4 OutColor[2] : SV_Target0" occupies output slot SV_Target0 and SV_Target1.
|
|
for (uint32 FlattenedArrayIndex = 0; FlattenedArrayIndex < FlattenedArrayDim; ++FlattenedArrayIndex)
|
|
{
|
|
const uint32 BindingSlot = Attribute.location + FlattenedArrayIndex;
|
|
MetaDataPrintf(
|
|
OutMetaData,
|
|
TEXT("%s[%d];%d:%s%d"),
|
|
*TypeSpecifier, // Type specifier
|
|
Attribute.array.dims[0], // Outer most array dimension
|
|
BindingSlot,
|
|
*Semantic,
|
|
BindingSlot
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const uint32 BindingSlot = Attribute.location;
|
|
MetaDataPrintf(
|
|
OutMetaData,
|
|
TEXT("%s[%d];%d:%s%d"),
|
|
*TypeSpecifier, // Type specifier
|
|
Attribute.array.dims[0], // Outer most array dimension
|
|
BindingSlot,
|
|
*Semantic,
|
|
BindingSlot
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MetaDataPrintf(
|
|
OutMetaData,
|
|
TEXT("%s;%d:%s"),
|
|
*TypeSpecifier, // type specifier
|
|
Attribute.location,
|
|
*Semantic
|
|
);
|
|
}
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteUniformBlock(const TCHAR* ResourceName, uint32 BindingIndex)
|
|
{
|
|
MetaDataPrintf(Strings.UniformBlocks, TEXT("%s(%u)"), ResourceName, BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WritePackedGlobal(const TCHAR* ResourceName, const TCHAR* TypeSpecifier, uint32 ByteOffset, uint32 ByteSize)
|
|
{
|
|
checkf(ByteOffset % 4 == 0, TEXT("field offset in @PackedGlobals shader meta data must be a multiple of 4, but got %u"), ByteOffset);
|
|
checkf(ByteSize % 4 == 0, TEXT("field size in @PackedGlobals shader meta data must be a multiple of 4, but got %u"), ByteSize);
|
|
MetaDataPrintf(Strings.PackedGlobals, TEXT("%s(%s:%u,%u)"), ResourceName, TypeSpecifier, ByteOffset / 4, ByteSize / 4);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WritePackedUB(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.PackedUB.IsEmpty(), TEXT("cannot define @PackedUB attribute more than once"));
|
|
MetaDataPrintf(Strings.PackedUB, TEXT("Globals(%u): "), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WritePackedUBField(const TCHAR* ResourceName, uint32 ByteOffset, uint32 ByteSize)
|
|
{
|
|
checkf(!Strings.PackedUB.IsEmpty(), TEXT("cannot append field without @PackedUB attribute in shader meta data"));
|
|
checkf(ByteOffset % 4 == 0, TEXT("field offset in @PackedUB shader meta data must be a multiple of 4, but got %u"), ByteOffset);
|
|
checkf(ByteSize % 4 == 0, TEXT("field size in @PackedUB shader meta data must be a multiple of 4, but got %u"), ByteSize);
|
|
MetaDataPrintf(Strings.PackedUBFields, TEXT("%s(%u,%u)"), ResourceName, ByteOffset / 4, ByteSize / 4);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WritePackedUBGlobalCopy(uint32 SourceCB, uint32 SourceOffset, uint32 DestCBIndex, uint32 DestCBPrecision, uint32 DestOffset, uint32 Size, bool bGroupFlattenedUBs)
|
|
{
|
|
if (bGroupFlattenedUBs)
|
|
{
|
|
MetaDataPrintf(Strings.PackedUBGlobalCopies, TEXT("%u:%u-%u:%c:%u:%u"), SourceCB, SourceOffset, DestCBIndex, DestCBPrecision, DestOffset, Size);
|
|
}
|
|
else
|
|
{
|
|
check(DestCBIndex == 0);
|
|
MetaDataPrintf(Strings.PackedUBGlobalCopies, TEXT("%u:%u-%c:%u:%u"), SourceCB, SourceOffset, DestCBPrecision, DestOffset, Size);
|
|
}
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteSRV(const TCHAR* ResourceName, uint32 BindingIndex, uint32 Count)
|
|
{
|
|
MetaDataPrintf(Strings.SRVs, TEXT("%s(%u:%u)"), ResourceName, BindingIndex, Count);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteSRV(const TCHAR* ResourceName, uint32 BindingIndex, uint32 Count, const TArray<FString>& AssociatedResourceNames)
|
|
{
|
|
MetaDataPrintf(Strings.SRVs, TEXT("%s(%u:%u"), ResourceName, BindingIndex, Count);
|
|
|
|
if (!AssociatedResourceNames.IsEmpty())
|
|
{
|
|
Strings.SRVs += TEXT("[");
|
|
for (int32 ArrayIndex = 0; ArrayIndex < AssociatedResourceNames.Num(); ++ArrayIndex)
|
|
{
|
|
if (ArrayIndex > 0)
|
|
{
|
|
Strings.SRVs += TEXT(",");
|
|
}
|
|
Strings.SRVs += AssociatedResourceNames[ArrayIndex];
|
|
}
|
|
Strings.SRVs += TEXT("]");
|
|
}
|
|
|
|
Strings.SRVs += TEXT(")");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteUAV(const TCHAR* ResourceName, uint32 BindingIndex, uint32 Count)
|
|
{
|
|
MetaDataPrintf(Strings.UAVs, TEXT("%s(%u:%u)"), ResourceName, BindingIndex, Count);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteSamplerState(const TCHAR* ResourceName, uint32 BindingIndex)
|
|
{
|
|
MetaDataPrintf(Strings.SamplerStates, TEXT("%u:%s"), BindingIndex, ResourceName);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteNumThreads(uint32 NumThreadsX, uint32 NumThreadsY, uint32 NumThreadsZ)
|
|
{
|
|
MetaDataPrintf(Strings.NumThreads, TEXT("%u, %u, %u"), NumThreadsX, NumThreadsY, NumThreadsZ);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteSideTable(const TCHAR* ResourceName, uint32 SideTableIndex)
|
|
{
|
|
MetaDataPrintf(Strings.SideTable, TEXT("%s(%d)"), ResourceName, SideTableIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteArgumentBuffers(uint32 BindingIndex, const TArray<uint32>& ResourceIndices)
|
|
{
|
|
MetaDataPrintf(Strings.ArgumentBuffers, TEXT("%d["), BindingIndex);
|
|
|
|
for (int32 ArrayIndex = 0; ArrayIndex < ResourceIndices.Num(); ++ArrayIndex)
|
|
{
|
|
if (ArrayIndex > 0)
|
|
{
|
|
Strings.ArgumentBuffers += TEXT(",");
|
|
}
|
|
Strings.ArgumentBuffers += FString::Printf(TEXT("%u"), ResourceIndices[ArrayIndex]);
|
|
}
|
|
|
|
Strings.ArgumentBuffers += TEXT("]");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationInputControlPoints(uint32 PatchSize)
|
|
{
|
|
checkf(Strings.TessellationInputControlPoints.IsEmpty(), TEXT("cannot define @TessellationInputControlPoints attribute more than once"));
|
|
Strings.TessellationInputControlPoints = FString::Printf(TEXT("%u"), PatchSize);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationOutputControlPoints(uint32 PatchSize)
|
|
{
|
|
checkf(Strings.TessellationOutputControlPoints.IsEmpty(), TEXT("cannot define @TessellationOutputControlPoints attribute more than once"));
|
|
Strings.TessellationOutputControlPoints = FString::Printf(TEXT("%u"), PatchSize);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationMaxTessFactor(uint32 MaxTessFactor)
|
|
{
|
|
checkf(Strings.TessellationMaxTessFactor.IsEmpty(), TEXT("cannot define @TessellationMaxTessFactor attribute more than once"));
|
|
Strings.TessellationMaxTessFactor = FString::Printf(TEXT("%u"), MaxTessFactor);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationDomainTri()
|
|
{
|
|
checkf(Strings.TessellationDomain.IsEmpty(), TEXT("cannot define @TessellationDomain attribute more than once"));
|
|
Strings.TessellationDomain = TEXT("tri");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationDomainQuad()
|
|
{
|
|
checkf(Strings.TessellationDomain.IsEmpty(), TEXT("cannot define @TessellationDomain attribute more than once"));
|
|
Strings.TessellationDomain = TEXT("quad");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationOutputWindingCW()
|
|
{
|
|
checkf(Strings.TessellationOutputWinding.IsEmpty(), TEXT("cannot define @TessellationOutputWinding attribute more than once"));
|
|
Strings.TessellationOutputWinding = TEXT("cw");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationOutputWindingCCW()
|
|
{
|
|
checkf(Strings.TessellationOutputWinding.IsEmpty(), TEXT("cannot define @TessellationOutputWinding attribute more than once"));
|
|
Strings.TessellationOutputWinding = TEXT("ccw");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationPartitioningInteger()
|
|
{
|
|
checkf(Strings.TessellationPartitioning.IsEmpty(), TEXT("cannot define @TessellationPartitioning attribute more than once"));
|
|
Strings.TessellationPartitioning = TEXT("integer");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationPartitioningFractionalOdd()
|
|
{
|
|
checkf(Strings.TessellationPartitioning.IsEmpty(), TEXT("cannot define @TessellationPartitioning attribute more than once"));
|
|
Strings.TessellationPartitioning = TEXT("fractional_odd");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationPartitioningFractionalEven()
|
|
{
|
|
checkf(Strings.TessellationPartitioning.IsEmpty(), TEXT("cannot define @TessellationPartitioning attribute more than once"));
|
|
Strings.TessellationPartitioning = TEXT("fractional_even");
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationPatchesPerThreadGroup(uint32 NumPatches)
|
|
{
|
|
checkf(Strings.TessellationPatchesPerThreadGroup.IsEmpty(), TEXT("cannot define @TessellationPatchesPerThreadGroup attribute more than once"));
|
|
Strings.TessellationPatchesPerThreadGroup = FString::Printf(TEXT("%u"), NumPatches);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationPatchCountBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationPatchCountBuffer.IsEmpty(), TEXT("cannot define @TessellationPatchCountBuffer attribute more than once"));
|
|
Strings.TessellationPatchCountBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationIndexBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationIndexBuffer.IsEmpty(), TEXT("cannot define @TessellationIndexBuffer attribute more than once"));
|
|
Strings.TessellationIndexBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationHSOutBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationHSOutBuffer.IsEmpty(), TEXT("cannot define @TessellationHSOutBuffer attribute more than once"));
|
|
Strings.TessellationHSOutBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationHSTFOutBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationHSTFOutBuffer.IsEmpty(), TEXT("cannot define @TessellationHSTFOutBuffer attribute more than once"));
|
|
Strings.TessellationHSTFOutBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationControlPointOutBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationControlPointOutBuffer.IsEmpty(), TEXT("cannot define @TessellationControlPointOutBuffer attribute more than once"));
|
|
Strings.TessellationControlPointOutBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
void FHlslccHeaderWriter::WriteTessellationControlPointIndexBuffer(uint32 BindingIndex)
|
|
{
|
|
checkf(Strings.TessellationControlPointIndexBuffer.IsEmpty(), TEXT("cannot define @TessellationControlPointIndexBuffer attribute more than once"));
|
|
Strings.TessellationControlPointIndexBuffer = FString::Printf(TEXT("%u"), BindingIndex);
|
|
}
|
|
|
|
FString FHlslccHeaderWriter::ToString() const
|
|
{
|
|
FString MetaData;
|
|
|
|
auto PrintAttributes = [&MetaData](const TCHAR* Name, const FString& Value)
|
|
{
|
|
if (!Value.IsEmpty())
|
|
{
|
|
MetaData += FString::Printf(TEXT("// @%s: %s\n"), Name, *Value);
|
|
}
|
|
};
|
|
|
|
PrintAttributes(TEXT("Inputs"), Strings.InputAttributes);
|
|
PrintAttributes(TEXT("Outputs"), Strings.OutputAttributes);
|
|
PrintAttributes(TEXT("UniformBlocks"), Strings.UniformBlocks);
|
|
PrintAttributes(TEXT("PackedUB"), Strings.PackedUB + Strings.PackedUBFields);
|
|
PrintAttributes(TEXT("PackedGlobals"), Strings.PackedGlobals);
|
|
PrintAttributes(TEXT("PackedUBGlobalCopies"), Strings.PackedUBGlobalCopies);
|
|
PrintAttributes(TEXT("Samplers"), Strings.SRVs); // Was called "Samplers" in HLSLcc but serves as SRVs
|
|
PrintAttributes(TEXT("UAVs"), Strings.UAVs);
|
|
PrintAttributes(TEXT("SamplerStates"), Strings.SamplerStates);
|
|
PrintAttributes(TEXT("NumThreads"), Strings.NumThreads);
|
|
PrintAttributes(TEXT("SideTable"), Strings.SideTable);
|
|
PrintAttributes(TEXT("ArgumentBuffers"), Strings.ArgumentBuffers);
|
|
PrintAttributes(TEXT("TessellationOutputControlPoints"), Strings.TessellationOutputControlPoints);
|
|
PrintAttributes(TEXT("TessellationDomain"), Strings.TessellationDomain);
|
|
PrintAttributes(TEXT("TessellationInputControlPoints"), Strings.TessellationInputControlPoints);
|
|
PrintAttributes(TEXT("TessellationMaxTessFactor"), Strings.TessellationMaxTessFactor);
|
|
PrintAttributes(TEXT("TessellationOutputWinding"), Strings.TessellationOutputWinding);
|
|
PrintAttributes(TEXT("TessellationPartitioning"), Strings.TessellationPartitioning);
|
|
PrintAttributes(TEXT("TessellationPatchesPerThreadGroup"), Strings.TessellationPatchesPerThreadGroup);
|
|
PrintAttributes(TEXT("TessellationPatchCountBuffer"), Strings.TessellationPatchCountBuffer);
|
|
PrintAttributes(TEXT("TessellationIndexBuffer"), Strings.TessellationIndexBuffer);
|
|
PrintAttributes(TEXT("TessellationHSOutBuffer"), Strings.TessellationHSOutBuffer);
|
|
PrintAttributes(TEXT("TessellationControlPointOutBuffer"), Strings.TessellationControlPointOutBuffer);
|
|
PrintAttributes(TEXT("TessellationHSTFOutBuffer"), Strings.TessellationHSTFOutBuffer);
|
|
PrintAttributes(TEXT("TessellationControlPointIndexBuffer"), Strings.TessellationControlPointIndexBuffer);
|
|
|
|
return MetaData;
|
|
}
|
|
|
|
} // namespace CrossCompiler
|