Files
UnrealEngineUWP/Engine/Source/Runtime/RenderCore/Public/CrossCompilerCommon.h
Ryan Vance 96bac36aa9 VKRT:
Add ray tracing shader types
Add initial ray tracing pipeline creation
Add acceleration structure descriptor type
Add basic ray tracing pipeline, occlusion support initially
Strip reflection from ray tracing shader spirv to deal with validation warnings
Don't use an array of vk descriptor types directly, this breaks with non-contiguous enum values which are common in extensions. Using a TMap from descriptor type to values instead.
Don't store vk types in the serialized shader header, translate to and from our own internal enum types to avoid similar non-contiguous value issues.
Re-enabled ray tracing compilation on windows desktop, explicitly disable runtime support using GRHISupportsRayTracing

Todo:
We need to deal with the lack of a 1:1 mapping between shader stages and frequencies for ray tracing hit groups. This is a one to many mapping which doesn't work with how most of the Vulkan RHI is authored. For now I'm assuming a hitgroup maps to a CHS.
Ray tracing shader descriptor allocation and pending state support. While we are serializing the descriptors for ray tracing shaders, we're not allocating or updating them yet which is the last large chunk needed to trace rays.
Fix spirv binary version mismatch validation error. This basically needs a local dxc modification which explicitly sets the spirv binary version to work around incorrect assuptions in dxc which is causing validation failures.
Add another local dxc modification to allow for arbirary struct size support using VK_EXT_scalar_block_layout for ray tracing shaders.

#rb jeannoe.morissette, lukas.hermanns

[CL 16711940 by Ryan Vance in ue5-main branch]
2021-06-17 17:15:16 -04:00

277 lines
7.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
CrossCompilerCommon.h: Common functionality between compiler & runtime.
=============================================================================*/
#pragma once
#include "CoreMinimal.h"
#include "ShaderCore.h"
#include "ShaderCompilerCore.h"
namespace CrossCompiler
{
enum EShaderStage
{
SHADER_STAGE_VERTEX = 0,
SHADER_STAGE_PIXEL,
SHADER_STAGE_GEOMETRY,
SHADER_STAGE_HULL,
SHADER_STAGE_DOMAIN,
NUM_NON_COMPUTE_SHADER_STAGES,
SHADER_STAGE_COMPUTE = NUM_NON_COMPUTE_SHADER_STAGES,
NUM_SHADER_STAGES,
};
// Make sure these enums match hlslcc EArray on Engine\Source\ThirdParty\hlslcc\hlslcc\src\hlslcc_lib\glsl_parser_extras.h
enum class EPackedTypeName : int8
{
HighP = 'h',
MediumP = 'm',
LowP = 'l',
Int = 'i',
Uint = 'u',
Sampler = 's',
Image = 'g',
Invalid = ' ',
};
enum class EPackedTypeIndex : int8
{
HighP = 0,
MediumP = 1,
LowP = 2,
Int = 3,
Uint = 4,
Sampler = 5,
Image = 6,
Max = 7,
Invalid = -1,
};
enum
{
PACKED_TYPENAME_HIGHP = (int32)EPackedTypeName::HighP, // Make sure these enums match hlslcc
PACKED_TYPENAME_MEDIUMP = (int32)EPackedTypeName::MediumP,
PACKED_TYPENAME_LOWP = (int32)EPackedTypeName::LowP,
PACKED_TYPENAME_INT = (int32)EPackedTypeName::Int,
PACKED_TYPENAME_UINT = (int32)EPackedTypeName::Uint,
PACKED_TYPENAME_SAMPLER = (int32)EPackedTypeName::Sampler,
PACKED_TYPENAME_IMAGE = (int32)EPackedTypeName::Image,
PACKED_TYPEINDEX_HIGHP = (int32)EPackedTypeIndex::HighP,
PACKED_TYPEINDEX_MEDIUMP = (int32)EPackedTypeIndex::MediumP,
PACKED_TYPEINDEX_LOWP = (int32)EPackedTypeIndex::LowP,
PACKED_TYPEINDEX_INT = (int32)EPackedTypeIndex::Int,
PACKED_TYPEINDEX_UINT = (int32)EPackedTypeIndex::Uint,
PACKED_TYPEINDEX_SAMPLER = (int32)EPackedTypeIndex::Sampler,
PACKED_TYPEINDEX_IMAGE = (int32)EPackedTypeIndex::Image,
PACKED_TYPEINDEX_MAX = (int32)EPackedTypeIndex::Max,
};
static FORCEINLINE uint8 ShaderStageIndexToTypeName(uint8 ShaderStage)
{
switch (ShaderStage)
{
case SHADER_STAGE_VERTEX: return 'v';
case SHADER_STAGE_PIXEL: return 'p';
case SHADER_STAGE_GEOMETRY: return 'g';
case SHADER_STAGE_HULL: return 'h';
case SHADER_STAGE_DOMAIN: return 'd';
case SHADER_STAGE_COMPUTE: return 'c';
default: break;
}
check(0);
return 0;
}
static FORCEINLINE uint8 PackedTypeIndexToTypeName(uint8 ArrayType)
{
switch (ArrayType)
{
case PACKED_TYPEINDEX_HIGHP: return PACKED_TYPENAME_HIGHP;
case PACKED_TYPEINDEX_MEDIUMP: return PACKED_TYPENAME_MEDIUMP;
case PACKED_TYPEINDEX_LOWP: return PACKED_TYPENAME_LOWP;
case PACKED_TYPEINDEX_INT: return PACKED_TYPENAME_INT;
case PACKED_TYPEINDEX_UINT: return PACKED_TYPENAME_UINT;
case PACKED_TYPEINDEX_SAMPLER: return PACKED_TYPENAME_SAMPLER;
case PACKED_TYPEINDEX_IMAGE: return PACKED_TYPENAME_IMAGE;
default: break;
}
check(0);
return 0;
}
static FORCEINLINE uint8 PackedTypeNameToTypeIndex(uint8 ArrayName)
{
switch (ArrayName)
{
case PACKED_TYPENAME_HIGHP: return PACKED_TYPEINDEX_HIGHP;
case PACKED_TYPENAME_MEDIUMP: return PACKED_TYPEINDEX_MEDIUMP;
case PACKED_TYPENAME_LOWP: return PACKED_TYPEINDEX_LOWP;
case PACKED_TYPENAME_INT: return PACKED_TYPEINDEX_INT;
case PACKED_TYPENAME_UINT: return PACKED_TYPEINDEX_UINT;
case PACKED_TYPENAME_SAMPLER: return PACKED_TYPEINDEX_SAMPLER;
case PACKED_TYPENAME_IMAGE: return PACKED_TYPEINDEX_IMAGE;
default: break;
}
check(0);
return 0;
}
static FORCEINLINE bool IsValidPackedTypeName(EPackedTypeName TypeName)
{
switch (TypeName)
{
case EPackedTypeName::HighP:
case EPackedTypeName::MediumP:
case EPackedTypeName::LowP:
case EPackedTypeName::Int:
case EPackedTypeName::Uint:
case EPackedTypeName::Sampler:
case EPackedTypeName::Image:
return true;
default: break;
}
return false;
}
static FORCEINLINE EPackedTypeName PackedTypeIndexToTypeName(EPackedTypeIndex TypeIndex)
{
switch (TypeIndex)
{
case EPackedTypeIndex::HighP: return EPackedTypeName::HighP;
case EPackedTypeIndex::MediumP: return EPackedTypeName::MediumP;
case EPackedTypeIndex::LowP: return EPackedTypeName::LowP;
case EPackedTypeIndex::Int: return EPackedTypeName::Int;
case EPackedTypeIndex::Uint: return EPackedTypeName::Uint;
case EPackedTypeIndex::Sampler: return EPackedTypeName::Sampler;
case EPackedTypeIndex::Image: return EPackedTypeName::Image;
default: break;
}
return EPackedTypeName::Invalid;
}
static FORCEINLINE EPackedTypeIndex PackedTypeNameToTypeIndex(EPackedTypeName TypeName)
{
switch (TypeName)
{
case EPackedTypeName::HighP: return EPackedTypeIndex::HighP;
case EPackedTypeName::MediumP: return EPackedTypeIndex::MediumP;
case EPackedTypeName::LowP: return EPackedTypeIndex::LowP;
case EPackedTypeName::Int: return EPackedTypeIndex::Int;
case EPackedTypeName::Uint: return EPackedTypeIndex::Uint;
case EPackedTypeName::Sampler: return EPackedTypeIndex::Sampler;
case EPackedTypeName::Image: return EPackedTypeIndex::Image;
default: break;
}
return EPackedTypeIndex::Invalid;
}
struct FPackedArrayInfo
{
uint16 Size; // Bytes
uint8 TypeName; // PACKED_TYPENAME
uint8 TypeIndex; // PACKED_TYPE
};
inline FArchive& operator<<(FArchive& Ar, FPackedArrayInfo& Info)
{
Ar << Info.Size;
Ar << Info.TypeName;
Ar << Info.TypeIndex;
return Ar;
}
#pragma warning(push)
#pragma warning(error : 4596)
struct FShaderBindingInOutMask
{
uint32 Bitmask = 0;
/** Maximum value for a valid index in this bitmask. */
static constexpr int32 MaxIndex = (sizeof(decltype(FShaderBindingInOutMask::Bitmask)) * 8u) - 1u;
/** Index to mark the binding of a depth-stencil output resource. */
static constexpr int32 DepthStencilMaskIndex = MaxIndex;
/** Sets the specified bitfield in this bitmask and validates its index boundary. */
FORCEINLINE void EnableField(int32 Index)
{
ensure(Index >= 0 && Index <= FShaderBindingInOutMask::MaxIndex);
Bitmask |= (1u << Index);
}
/** Returns whether the specified bitfield in this bitmask is set and validates its index boundary. */
FORCEINLINE bool IsFieldEnabled(int32 Index) const
{
ensure(Index >= 0 && Index <= FShaderBindingInOutMask::MaxIndex);
return (Bitmask & (1u << Index)) != 0;
}
friend bool operator == (const FShaderBindingInOutMask& Lhs, const FShaderBindingInOutMask& Rhs)
{
return Lhs.Bitmask == Rhs.Bitmask;
}
friend bool operator != (const FShaderBindingInOutMask& Lhs, const FShaderBindingInOutMask& Rhs)
{
return !(Lhs == Rhs);
}
};
#pragma warning(pop)
inline FArchive& operator<<(FArchive& Ar, FShaderBindingInOutMask& BindingInOutMask)
{
Ar << BindingInOutMask.Bitmask;
return Ar;
}
struct FShaderBindings
{
TArray<TArray<FPackedArrayInfo>> PackedUniformBuffers;
TArray<FPackedArrayInfo> PackedGlobalArrays;
FShaderCompilerResourceTable ShaderResourceTable;
FShaderBindingInOutMask InOutMask;
uint8 NumSamplers;
uint8 NumUniformBuffers;
uint8 NumUAVs;
uint8 NumAccelerationStructures;
bool bHasRegularUniformBuffers;
};
// Information for copying members from uniform buffers to packed
struct FUniformBufferCopyInfo
{
uint16 SourceOffsetInFloats;
uint8 SourceUBIndex;
uint8 DestUBIndex;
uint8 DestUBTypeName;
uint8 DestUBTypeIndex;
uint16 DestOffsetInFloats;
uint16 SizeInFloats;
};
inline FArchive& operator<<(FArchive& Ar, FUniformBufferCopyInfo& Info)
{
Ar << Info.SourceOffsetInFloats;
Ar << Info.SourceUBIndex;
Ar << Info.DestUBIndex;
Ar << Info.DestUBTypeName;
if (Ar.IsLoading())
{
Info.DestUBTypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(Info.DestUBTypeName);
}
Ar << Info.DestOffsetInFloats;
Ar << Info.SizeInFloats;
return Ar;
}
}