blob: 3be7247fd12429e12b143f0bf1585b9f4f63c212 [file] [log] [blame]
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UtilsHLSL.cpp:
// Utility methods for GLSL to HLSL translation.
//
#include "compiler/translator/UtilsHLSL.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/util.h"
namespace sh
{
namespace
{
void DisambiguateFunctionNameForParameterType(const TType &paramType,
TString *disambiguatingStringOut)
{
// Parameter types are only added to function names if they are ambiguous according to the
// native HLSL compiler. Other parameter types are not added to function names to avoid
// making function names longer.
if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat)
{
// Disambiguation is needed for float2x2 and float4 parameters. These are the only
// built-in types that HLSL thinks are identical. float2x3 and float3x2 are different
// types, for example.
*disambiguatingStringOut += "_" + TypeString(paramType);
}
else if (paramType.getBasicType() == EbtStruct)
{
// Disambiguation is needed for struct parameters, since HLSL thinks that structs with
// the same fields but a different name are identical.
ASSERT(paramType.getStruct()->symbolType() != SymbolType::Empty);
*disambiguatingStringOut += "_" + TypeString(paramType);
}
}
} // anonymous namespace
const char *SamplerString(const TBasicType type)
{
if (IsShadowSampler(type))
{
return "SamplerComparisonState";
}
else
{
return "SamplerState";
}
}
const char *SamplerString(HLSLTextureGroup type)
{
if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
{
return "SamplerComparisonState";
}
else
{
return "SamplerState";
}
}
HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtSampler2D:
return HLSL_TEXTURE_2D;
case EbtSamplerCube:
return HLSL_TEXTURE_CUBE;
case EbtSamplerExternalOES:
return HLSL_TEXTURE_2D;
case EbtSampler2DArray:
return HLSL_TEXTURE_2D_ARRAY;
case EbtSampler3D:
return HLSL_TEXTURE_3D;
case EbtSampler2DMS:
return HLSL_TEXTURE_2D_MS;
case EbtSampler2DMSArray:
return HLSL_TEXTURE_2D_MS_ARRAY;
case EbtISampler2D:
return HLSL_TEXTURE_2D_INT4;
case EbtISampler3D:
return HLSL_TEXTURE_3D_INT4;
case EbtISamplerCube:
return HLSL_TEXTURE_2D_ARRAY_INT4;
case EbtISampler2DArray:
return HLSL_TEXTURE_2D_ARRAY_INT4;
case EbtISampler2DMS:
return HLSL_TEXTURE_2D_MS_INT4;
case EbtISampler2DMSArray:
return HLSL_TEXTURE_2D_MS_ARRAY_INT4;
case EbtUSampler2D:
return HLSL_TEXTURE_2D_UINT4;
case EbtUSampler3D:
return HLSL_TEXTURE_3D_UINT4;
case EbtUSamplerCube:
return HLSL_TEXTURE_2D_ARRAY_UINT4;
case EbtUSampler2DArray:
return HLSL_TEXTURE_2D_ARRAY_UINT4;
case EbtUSampler2DMS:
return HLSL_TEXTURE_2D_MS_UINT4;
case EbtUSampler2DMSArray:
return HLSL_TEXTURE_2D_MS_ARRAY_UINT4;
case EbtSampler2DShadow:
return HLSL_TEXTURE_2D_COMPARISON;
case EbtSamplerCubeShadow:
return HLSL_TEXTURE_CUBE_COMPARISON;
case EbtSampler2DArrayShadow:
return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
case EbtImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_2D;
case EiifRGBA8:
return HLSL_TEXTURE_2D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_2D_SNORM;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtIImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_2D_INT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtUImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_2D_UINT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_3D;
case EiifRGBA8:
return HLSL_TEXTURE_3D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_3D_SNORM;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtIImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_3D_INT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtUImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_3D_UINT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtImage2DArray:
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_TEXTURE_2D_ARRAY;
case EiifRGBA8:
return HLSL_TEXTURE_2D_ARRAY_UNORN;
case EiifRGBA8_SNORM:
return HLSL_TEXTURE_2D_ARRAY_SNORM;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtIImage2DArray:
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_TEXTURE_2D_ARRAY_INT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
case EbtUImage2DArray:
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_TEXTURE_2D_ARRAY_UINT4;
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
default:
UNREACHABLE();
#if !UNREACHABLE_IS_NORETURN
return HLSL_TEXTURE_UNKNOWN;
#endif
}
}
const char *TextureString(const HLSLTextureGroup textureGroup)
{
switch (textureGroup)
{
case HLSL_TEXTURE_2D:
return "Texture2D<float4>";
case HLSL_TEXTURE_CUBE:
return "TextureCube<float4>";
case HLSL_TEXTURE_2D_ARRAY:
return "Texture2DArray<float4>";
case HLSL_TEXTURE_3D:
return "Texture3D<float4>";
case HLSL_TEXTURE_2D_UNORM:
return "Texture2D<unorm float4>";
case HLSL_TEXTURE_CUBE_UNORM:
return "TextureCube<unorm float4>";
case HLSL_TEXTURE_2D_ARRAY_UNORN:
return "Texture2DArray<unorm float4>";
case HLSL_TEXTURE_3D_UNORM:
return "Texture3D<unorm float4>";
case HLSL_TEXTURE_2D_SNORM:
return "Texture2D<snorm float4>";
case HLSL_TEXTURE_CUBE_SNORM:
return "TextureCube<snorm float4>";
case HLSL_TEXTURE_2D_ARRAY_SNORM:
return "Texture2DArray<snorm float4>";
case HLSL_TEXTURE_3D_SNORM:
return "Texture3D<snorm float4>";
case HLSL_TEXTURE_2D_MS:
return "Texture2DMS<float4>";
case HLSL_TEXTURE_2D_MS_ARRAY:
return "Texture2DMSArray<float4>";
case HLSL_TEXTURE_2D_INT4:
return "Texture2D<int4>";
case HLSL_TEXTURE_3D_INT4:
return "Texture3D<int4>";
case HLSL_TEXTURE_2D_ARRAY_INT4:
return "Texture2DArray<int4>";
case HLSL_TEXTURE_2D_MS_INT4:
return "Texture2DMS<int4>";
case HLSL_TEXTURE_2D_MS_ARRAY_INT4:
return "Texture2DMSArray<int4>";
case HLSL_TEXTURE_2D_UINT4:
return "Texture2D<uint4>";
case HLSL_TEXTURE_3D_UINT4:
return "Texture3D<uint4>";
case HLSL_TEXTURE_2D_ARRAY_UINT4:
return "Texture2DArray<uint4>";
case HLSL_TEXTURE_2D_MS_UINT4:
return "Texture2DMS<uint4>";
case HLSL_TEXTURE_2D_MS_ARRAY_UINT4:
return "Texture2DMSArray<uint4>";
case HLSL_TEXTURE_2D_COMPARISON:
return "Texture2D";
case HLSL_TEXTURE_CUBE_COMPARISON:
return "TextureCube";
case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
return "Texture2DArray";
default:
UNREACHABLE();
}
return "<unknown read texture type>";
}
const char *TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
return TextureString(TextureGroup(type, imageInternalFormat));
}
const char *TextureGroupSuffix(const HLSLTextureGroup type)
{
switch (type)
{
case HLSL_TEXTURE_2D:
return "2D";
case HLSL_TEXTURE_CUBE:
return "Cube";
case HLSL_TEXTURE_2D_ARRAY:
return "2DArray";
case HLSL_TEXTURE_3D:
return "3D";
case HLSL_TEXTURE_2D_UNORM:
return "2D_unorm_float4_";
case HLSL_TEXTURE_CUBE_UNORM:
return "Cube_unorm_float4_";
case HLSL_TEXTURE_2D_ARRAY_UNORN:
return "2DArray_unorm_float4_";
case HLSL_TEXTURE_3D_UNORM:
return "3D_unorm_float4_";
case HLSL_TEXTURE_2D_SNORM:
return "2D_snorm_float4_";
case HLSL_TEXTURE_CUBE_SNORM:
return "Cube_snorm_float4_";
case HLSL_TEXTURE_2D_ARRAY_SNORM:
return "2DArray_snorm_float4_";
case HLSL_TEXTURE_3D_SNORM:
return "3D_snorm_float4_";
case HLSL_TEXTURE_2D_MS:
return "2DMS";
case HLSL_TEXTURE_2D_MS_ARRAY:
return "2DMSArray";
case HLSL_TEXTURE_2D_INT4:
return "2D_int4_";
case HLSL_TEXTURE_3D_INT4:
return "3D_int4_";
case HLSL_TEXTURE_2D_ARRAY_INT4:
return "2DArray_int4_";
case HLSL_TEXTURE_2D_MS_INT4:
return "2DMS_int4_";
case HLSL_TEXTURE_2D_MS_ARRAY_INT4:
return "2DMSArray_int4_";
case HLSL_TEXTURE_2D_UINT4:
return "2D_uint4_";
case HLSL_TEXTURE_3D_UINT4:
return "3D_uint4_";
case HLSL_TEXTURE_2D_ARRAY_UINT4:
return "2DArray_uint4_";
case HLSL_TEXTURE_2D_MS_UINT4:
return "2DMS_uint4_";
case HLSL_TEXTURE_2D_MS_ARRAY_UINT4:
return "2DMSArray_uint4_";
case HLSL_TEXTURE_2D_COMPARISON:
return "2D_comparison";
case HLSL_TEXTURE_CUBE_COMPARISON:
return "Cube_comparison";
case HLSL_TEXTURE_2D_ARRAY_COMPARISON:
return "2DArray_comparison";
default:
UNREACHABLE();
}
return "<unknown texture type>";
}
const char *TextureGroupSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat)
{
return TextureGroupSuffix(TextureGroup(type, imageInternalFormat));
}
const char *TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtISamplerCube:
return "Cube_int4_";
case EbtUSamplerCube:
return "Cube_uint4_";
case EbtSamplerExternalOES:
return "_External";
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return "Cube_float4_";
case EiifRGBA8:
return "Cube_unorm_float4_";
case EiifRGBA8_SNORM:
return "Cube_snorm_float4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return "Cube_int4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return "Cube_uint4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
default:
// All other types are identified by their group suffix
return TextureGroupSuffix(type, imageInternalFormat);
}
#if !UNREACHABLE_IS_NORETURN
UNREACHABLE();
return "_TTS_invalid_";
#endif
}
HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_2D_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_2D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_2D_SNORM;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtIImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_2D_INT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtUImage2D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_2D_UINT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_3D_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_3D_UNORM;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_3D_SNORM;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtIImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_3D_INT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtUImage3D:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_3D_UINT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtImage2DArray:
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4;
case EiifRGBA8:
return HLSL_RWTEXTURE_2D_ARRAY_UNORN;
case EiifRGBA8_SNORM:
return HLSL_RWTEXTURE_2D_ARRAY_SNORM;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtIImage2DArray:
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return HLSL_RWTEXTURE_2D_ARRAY_INT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtUImage2DArray:
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return HLSL_RWTEXTURE_2D_ARRAY_UINT4;
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
default:
UNREACHABLE();
}
return HLSL_RWTEXTURE_UNKNOWN;
}
const char *RWTextureString(const HLSLRWTextureGroup RWTextureGroup)
{
switch (RWTextureGroup)
{
case HLSL_RWTEXTURE_2D_FLOAT4:
return "RWTexture2D<float4>";
case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
return "RWTexture2DArray<float4>";
case HLSL_RWTEXTURE_3D_FLOAT4:
return "RWTexture3D<float4>";
case HLSL_RWTEXTURE_2D_UNORM:
return "RWTexture2D<unorm float4>";
case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
return "RWTexture2DArray<unorm float4>";
case HLSL_RWTEXTURE_3D_UNORM:
return "RWTexture3D<unorm float4>";
case HLSL_RWTEXTURE_2D_SNORM:
return "RWTexture2D<snorm float4>";
case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
return "RWTexture2DArray<snorm float4>";
case HLSL_RWTEXTURE_3D_SNORM:
return "RWTexture3D<snorm float4>";
case HLSL_RWTEXTURE_2D_UINT4:
return "RWTexture2D<uint4>";
case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
return "RWTexture2DArray<uint4>";
case HLSL_RWTEXTURE_3D_UINT4:
return "RWTexture3D<uint4>";
case HLSL_RWTEXTURE_2D_INT4:
return "RWTexture2D<int4>";
case HLSL_RWTEXTURE_2D_ARRAY_INT4:
return "RWTexture2DArray<int4>";
case HLSL_RWTEXTURE_3D_INT4:
return "RWTexture3D<int4>";
default:
UNREACHABLE();
}
return "<unknown read and write texture type>";
}
const char *RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
return RWTextureString(RWTextureGroup(type, imageInternalFormat));
}
const char *RWTextureGroupSuffix(const HLSLRWTextureGroup type)
{
switch (type)
{
case HLSL_RWTEXTURE_2D_FLOAT4:
return "RW2D_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
return "RW2DArray_float4_";
case HLSL_RWTEXTURE_3D_FLOAT4:
return "RW3D_float4_";
case HLSL_RWTEXTURE_2D_UNORM:
return "RW2D_unorm_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
return "RW2DArray_unorm_float4_";
case HLSL_RWTEXTURE_3D_UNORM:
return "RW3D_unorm_float4_";
case HLSL_RWTEXTURE_2D_SNORM:
return "RW2D_snorm_float4_";
case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
return "RW2DArray_snorm_float4_";
case HLSL_RWTEXTURE_3D_SNORM:
return "RW3D_snorm_float4_";
case HLSL_RWTEXTURE_2D_UINT4:
return "RW2D_uint4_";
case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
return "RW2DArray_uint4_";
case HLSL_RWTEXTURE_3D_UINT4:
return "RW3D_uint4_";
case HLSL_RWTEXTURE_2D_INT4:
return "RW2D_int4_";
case HLSL_RWTEXTURE_2D_ARRAY_INT4:
return "RW2DArray_int4_";
case HLSL_RWTEXTURE_3D_INT4:
return "RW3D_int4_";
default:
UNREACHABLE();
}
return "<unknown read and write resource>";
}
const char *RWTextureGroupSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat)
{
return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat));
}
const char *RWTextureTypeSuffix(const TBasicType type,
TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
case EbtImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32F:
case EiifRGBA16F:
case EiifR32F:
return "RWCube_float4_";
case EiifRGBA8:
return "RWCube_unorm_float4_";
case EiifRGBA8_SNORM:
return "RWCube_unorm_float4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtIImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32I:
case EiifRGBA16I:
case EiifRGBA8I:
case EiifR32I:
return "RWCube_int4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
case EbtUImageCube:
{
switch (imageInternalFormat)
{
case EiifRGBA32UI:
case EiifRGBA16UI:
case EiifRGBA8UI:
case EiifR32UI:
return "RWCube_uint4_";
default:
UNREACHABLE();
}
#if !UNREACHABLE_IS_NORETURN
break;
#endif
}
default:
// All other types are identified by their group suffix
return RWTextureGroupSuffix(type, imageInternalFormat);
}
#if !UNREACHABLE_IS_NORETURN
UNREACHABLE();
return "_RWTS_invalid_";
#endif
}
TString DecorateField(const ImmutableString &string, const TStructure &structure)
{
if (structure.symbolType() != SymbolType::BuiltIn)
{
return Decorate(string);
}
return TString(string.data());
}
TString DecoratePrivate(const ImmutableString &privateText)
{
return "dx_" + TString(privateText.data());
}
TString Decorate(const ImmutableString &string)
{
if (!string.beginsWith("gl_"))
{
return "_" + TString(string.data());
}
return TString(string.data());
}
TString DecorateVariableIfNeeded(const TVariable &variable)
{
if (variable.symbolType() == SymbolType::AngleInternal ||
variable.symbolType() == SymbolType::Empty)
{
// Besides handling internal variables, we generate names for nameless parameters here.
const ImmutableString &name = variable.name();
// The name should not have a prefix reserved for user-defined variables or functions.
ASSERT(!name.beginsWith("f_"));
ASSERT(!name.beginsWith("_"));
return TString(name.data());
}
// For user defined variables, combine variable name with unique id
// so variables of the same name in different scopes do not get overwritten.
else if (variable.symbolType() == SymbolType::UserDefined &&
variable.getType().getQualifier() == EvqTemporary)
{
return Decorate(variable.name()) + str(variable.uniqueId().get());
}
else
{
return Decorate(variable.name());
}
}
TString DecorateFunctionIfNeeded(const TFunction *func)
{
if (func->symbolType() == SymbolType::AngleInternal)
{
// The name should not have a prefix reserved for user-defined variables or functions.
ASSERT(!func->name().beginsWith("f_"));
ASSERT(!func->name().beginsWith("_"));
return TString(func->name().data());
}
ASSERT(!func->name().beginsWith("gl_"));
// Add an additional f prefix to functions so that they're always disambiguated from variables.
// This is necessary in the corner case where a variable declaration hides a function that it
// uses in its initializer.
return "f_" + TString(func->name().data());
}
TString TypeString(const TType &type)
{
const TStructure *structure = type.getStruct();
if (structure)
{
if (structure->symbolType() != SymbolType::Empty)
{
return StructNameString(*structure);
}
else // Nameless structure, define in place
{
return StructureHLSL::defineNameless(*structure);
}
}
else if (type.isMatrix())
{
int cols = type.getCols();
int rows = type.getRows();
return "float" + str(cols) + "x" + str(rows);
}
else
{
switch (type.getBasicType())
{
case EbtFloat:
switch (type.getNominalSize())
{
case 1:
return "float";
case 2:
return "float2";
case 3:
return "float3";
case 4:
return "float4";
}
case EbtInt:
switch (type.getNominalSize())
{
case 1:
return "int";
case 2:
return "int2";
case 3:
return "int3";
case 4:
return "int4";
}
case EbtUInt:
switch (type.getNominalSize())
{
case 1:
return "uint";
case 2:
return "uint2";
case 3:
return "uint3";
case 4:
return "uint4";
}
case EbtBool:
switch (type.getNominalSize())
{
case 1:
return "bool";
case 2:
return "bool2";
case 3:
return "bool3";
case 4:
return "bool4";
}
case EbtVoid:
return "void";
case EbtSampler2D:
case EbtISampler2D:
case EbtUSampler2D:
case EbtSampler2DArray:
case EbtISampler2DArray:
case EbtUSampler2DArray:
return "sampler2D";
case EbtSamplerCube:
case EbtISamplerCube:
case EbtUSamplerCube:
return "samplerCUBE";
case EbtSamplerExternalOES:
return "sampler2D";
case EbtAtomicCounter:
// Multiple atomic_uints will be implemented as a single RWByteAddressBuffer
return "RWByteAddressBuffer";
default:
break;
}
}
UNREACHABLE();
return "<unknown type>";
}
TString StructNameString(const TStructure &structure)
{
if (structure.symbolType() == SymbolType::Empty)
{
return "";
}
// For structures at global scope we use a consistent
// translation so that we can link between shader stages.
if (structure.atGlobalScope())
{
return Decorate(structure.name());
}
return "ss" + str(structure.uniqueId().get()) + "_" + TString(structure.name().data());
}
TString QualifiedStructNameString(const TStructure &structure,
bool useHLSLRowMajorPacking,
bool useStd140Packing)
{
if (structure.symbolType() == SymbolType::Empty)
{
return "";
}
TString prefix = "";
// Structs packed with row-major matrices in HLSL are prefixed with "rm"
// GLSL column-major maps to HLSL row-major, and the converse is true
if (useStd140Packing)
{
prefix += "std_";
}
if (useHLSLRowMajorPacking)
{
prefix += "rm_";
}
return prefix + StructNameString(structure);
}
const char *InterpolationString(TQualifier qualifier)
{
switch (qualifier)
{
case EvqVaryingIn:
return "";
case EvqFragmentIn:
return "";
case EvqSmoothIn:
return "linear";
case EvqFlatIn:
return "nointerpolation";
case EvqCentroidIn:
return "centroid";
case EvqVaryingOut:
return "";
case EvqVertexOut:
return "";
case EvqSmoothOut:
return "linear";
case EvqFlatOut:
return "nointerpolation";
case EvqCentroidOut:
return "centroid";
default:
UNREACHABLE();
}
return "";
}
const char *QualifierString(TQualifier qualifier)
{
switch (qualifier)
{
case EvqIn:
return "in";
case EvqOut:
return "inout"; // 'out' results in an HLSL error if not all fields are written, for
// GLSL it's undefined
case EvqInOut:
return "inout";
case EvqConstReadOnly:
return "const";
default:
UNREACHABLE();
}
return "";
}
TString DisambiguateFunctionName(const TFunction *func)
{
TString disambiguatingString;
size_t paramCount = func->getParamCount();
for (size_t i = 0; i < paramCount; ++i)
{
DisambiguateFunctionNameForParameterType(func->getParam(i)->getType(),
&disambiguatingString);
}
return disambiguatingString;
}
TString DisambiguateFunctionName(const TIntermSequence *args)
{
TString disambiguatingString;
for (TIntermNode *arg : *args)
{
ASSERT(arg->getAsTyped());
DisambiguateFunctionNameForParameterType(arg->getAsTyped()->getType(),
&disambiguatingString);
}
return disambiguatingString;
}
} // namespace sh