Merge with upstream

This commit is contained in:
Bill Hollings 2017-05-19 19:36:24 -04:00
commit d677e63860
22 changed files with 806 additions and 78 deletions

View File

@ -205,11 +205,16 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
{
fprintf(stderr, "%s\n", tag);
fprintf(stderr, "=============\n\n");
bool print_ssbo = !strcmp(tag, "ssbos");
for (auto &res : resources)
{
auto &type = compiler.get_type(res.type_id);
auto mask = compiler.get_decoration_mask(res.id);
if (print_ssbo && compiler.buffer_is_hlsl_counter_buffer(res.id))
continue;
// If we don't have a name, use the fallback for the type instead of the variable
// for SSBOs and UBOs since those are the only meaningful names to use externally.
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
@ -245,6 +250,10 @@ static void print_resources(const Compiler &compiler, const char *tag, const vec
fprintf(stderr, " readonly");
if (is_sized_block)
fprintf(stderr, " (BlockSize : %u bytes)", block_size);
uint32_t counter_id = 0;
if (print_ssbo && compiler.buffer_get_hlsl_counter_buffer(res.id, counter_id))
fprintf(stderr, " (HLSL counter buffer ID: %u)", counter_id);
fprintf(stderr, "\n");
}
fprintf(stderr, "=============\n\n");

View File

@ -0,0 +1,44 @@
Texture2D<float4> uSampler;
SamplerState _uSampler_sampler;
Texture2D<float4> uSamplerShadow;
SamplerComparisonState _uSamplerShadow_sampler;
static float FragColor;
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
float4 samp2(Texture2D<float4> s, SamplerState _s_sampler)
{
return s.Sample(_s_sampler, float2(1.0f, 1.0f)) + s.Load(int3(int2(10, 10), 0));
}
float4 samp3(Texture2D<float4> s, SamplerState _s_sampler)
{
return samp2(s, _s_sampler);
}
float samp4(Texture2D<float4> s, SamplerComparisonState _s_sampler)
{
return s.SampleCmp(_s_sampler, float3(1.0f, 1.0f, 1.0f).xy, float3(1.0f, 1.0f, 1.0f).z);
}
float samp(Texture2D<float4> s0, SamplerState _s0_sampler, Texture2D<float4> s1, SamplerComparisonState _s1_sampler)
{
return samp3(s0, _s0_sampler).x + samp4(s1, _s1_sampler);
}
void frag_main()
{
FragColor = samp(uSampler, _uSampler_sampler, uSamplerShadow, _uSamplerShadow_sampler);
}
SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,40 @@
Texture2D<float4> uDepth;
SamplerComparisonState uSampler;
SamplerState uSampler1;
static float FragColor;
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
float samp2(Texture2D<float4> t, SamplerComparisonState s)
{
return t.SampleCmp(s, float3(1.0f, 1.0f, 1.0f).xy, float3(1.0f, 1.0f, 1.0f).z);
}
float samp3(Texture2D<float4> t, SamplerState s)
{
return t.Sample(s, float2(1.0f, 1.0f)).x;
}
float samp(Texture2D<float4> t, SamplerComparisonState s, SamplerState s1)
{
float r0 = samp2(t, s);
float r1 = samp3(t, s1);
return r0 + r1;
}
void frag_main()
{
FragColor = samp(uDepth, uSampler, uSampler1);
}
SPIRV_Cross_Output main()
{
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -18,6 +18,10 @@ Texture2DArray<float4> tex2dArray;
SamplerState _tex2dArray_sampler;
TextureCubeArray<float4> texCubeArray;
SamplerState _texCubeArray_sampler;
Texture2D<float4> separateTex2d;
SamplerState samplerNonDepth;
Texture2D<float4> separateTex2dDepth;
SamplerComparisonState samplerDepth;
static float texCoord1d;
static float2 texCoord2d;
@ -87,6 +91,8 @@ void frag_main()
texcolor += texCubeArray.Sample(_texCubeArray_sampler, texCoord4d);
texcolor += tex2d.Gather(_tex2d_sampler, texCoord2d, 0);
texcolor += tex2d.Load(int3(int2(1, 2), 0));
texcolor += separateTex2d.Sample(samplerNonDepth, texCoord2d);
texcolor.w += separateTex2dDepth.SampleCmp(samplerDepth, texCoord3d.xy, texCoord3d.z);
FragColor = texcolor;
}

View File

@ -0,0 +1,24 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 FragColor [[color(0)]];
};
float4 samp(thread const texture2d<float> t, thread const sampler s)
{
return t.sample(s, float2(0.5));
}
fragment main0_out main0(texture2d<float> uDepth [[texture(0)]], sampler uSampler [[sampler(0)]])
{
main0_out out = {};
out.FragColor = samp(uDepth, uSampler);
return out;
}

View File

@ -0,0 +1,31 @@
#version 310 es
precision mediump float;
precision highp int;
uniform mediump sampler2DShadow SPIRV_Cross_CombineduDepthuSampler;
uniform mediump sampler2D SPIRV_Cross_CombineduDepthuSampler1;
layout(location = 0) out float FragColor;
float samp2(mediump sampler2DShadow SPIRV_Cross_Combinedts)
{
return texture(SPIRV_Cross_Combinedts, vec3(vec3(1.0).xy, vec3(1.0).z));
}
float samp3(mediump sampler2D SPIRV_Cross_Combinedts)
{
return texture(SPIRV_Cross_Combinedts, vec2(1.0)).x;
}
float samp(mediump sampler2DShadow SPIRV_Cross_Combinedts, mediump sampler2D SPIRV_Cross_Combinedts1)
{
float r0 = samp2(SPIRV_Cross_Combinedts);
float r1 = samp3(SPIRV_Cross_Combinedts1);
return r0 + r1;
}
void main()
{
FragColor = samp(SPIRV_Cross_CombineduDepthuSampler, SPIRV_Cross_CombineduDepthuSampler1);
}

View File

@ -0,0 +1,32 @@
#version 310 es
precision mediump float;
precision highp int;
layout(set = 0, binding = 2) uniform mediump texture2D uDepth;
layout(set = 0, binding = 0) uniform mediump samplerShadow uSampler;
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
layout(location = 0) out float FragColor;
float samp2(mediump texture2D t, mediump samplerShadow s)
{
return texture(sampler2DShadow(t, s), vec3(vec3(1.0).xy, vec3(1.0).z));
}
float samp3(mediump texture2D t, mediump sampler s)
{
return texture(sampler2D(t, s), vec2(1.0)).x;
}
float samp(mediump texture2D t, mediump samplerShadow s, mediump sampler s1)
{
float r0 = samp2(t, s);
float r1 = samp3(t, s1);
return r0 + r1;
}
void main()
{
FragColor = samp(uDepth, uSampler, uSampler1);
}

View File

@ -0,0 +1,31 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 1) uniform mediump sampler2D uSampler;
layout(set = 0, binding = 1) uniform mediump sampler2DShadow uSamplerShadow;
layout(location = 0) out float FragColor;
vec4 samp2(sampler2D s)
{
return texture(s, vec2(1.0)) + texelFetch(s, ivec2(10), 0);
}
vec4 samp3(sampler2D s)
{
return samp2(s);
}
float samp4(mediump sampler2DShadow s)
{
return texture(s, vec3(1.0));
}
float samp(sampler2D s0, mediump sampler2DShadow s1)
{
return samp3(s0).x + samp4(s1);
}
void main()
{
FragColor = samp(uSampler, uSamplerShadow);
}

View File

@ -0,0 +1,29 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump samplerShadow uSampler;
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
layout(set = 0, binding = 2) uniform texture2D uDepth;
layout(location = 0) out float FragColor;
float samp2(texture2D t, mediump samplerShadow s)
{
return texture(sampler2DShadow(t, s), vec3(1.0));
}
float samp3(texture2D t, mediump sampler s)
{
return texture(sampler2D(t, s), vec2(1.0)).x;
}
float samp(texture2D t, mediump samplerShadow s, mediump sampler s1)
{
float r0 = samp2(t, s);
float r1 = samp3(t, s1);
return r0 + r1;
}
void main()
{
FragColor = samp(uDepth, uSampler, uSampler1);
}

View File

@ -13,6 +13,11 @@ uniform sampler1DArray tex1dArray;
uniform sampler2DArray tex2dArray;
uniform samplerCubeArray texCubeArray;
uniform samplerShadow samplerDepth;
uniform sampler samplerNonDepth;
uniform texture2D separateTex2d;
uniform texture2D separateTex2dDepth;
in float texCoord1d;
in vec2 texCoord2d;
in vec3 texCoord3d;
@ -59,5 +64,8 @@ void main()
texcolor += texelFetch(tex2d, ivec2(1, 2), 0);
texcolor += texture(sampler2D(separateTex2d, samplerNonDepth), texCoord2d);
texcolor.a += texture(sampler2DShadow(separateTex2dDepth, samplerDepth), texCoord3d);
FragColor = texcolor;
}

View File

@ -0,0 +1,16 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump sampler uSampler;
layout(set = 0, binding = 1) uniform mediump texture2D uDepth;
layout(location = 0) out vec4 FragColor;
vec4 samp(texture2D t, mediump sampler s)
{
return texture(sampler2D(t, s), vec2(0.5));
}
void main()
{
FragColor = samp(uDepth, uSampler);
}

View File

@ -0,0 +1,29 @@
#version 310 es
precision mediump float;
layout(set = 0, binding = 0) uniform mediump samplerShadow uSampler;
layout(set = 0, binding = 1) uniform mediump sampler uSampler1;
layout(set = 0, binding = 2) uniform texture2D uDepth;
layout(location = 0) out float FragColor;
float samp2(texture2D t, mediump samplerShadow s)
{
return texture(sampler2DShadow(t, s), vec3(1.0));
}
float samp3(texture2D t, mediump sampler s)
{
return texture(sampler2D(t, s), vec2(1.0)).x;
}
float samp(texture2D t, mediump samplerShadow s, mediump sampler s1)
{
float r0 = samp2(t, s);
float r1 = samp3(t, s1);
return r0 + r1;
}
void main()
{
FragColor = samp(uDepth, uSampler, uSampler1);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2016 The Khronos Group Inc.
// Copyright (c) 2014-2017 The Khronos Group Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and/or associated documentation files (the "Materials"),
@ -47,11 +47,11 @@ namespace spv {
typedef unsigned int Id;
#define SPV_VERSION 0x10000
#define SPV_REVISION 5
#define SPV_REVISION 10
static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010000;
static const unsigned int Revision = 5;
static const unsigned int Revision = 10;
static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16;
@ -61,6 +61,8 @@ enum SourceLanguage {
SourceLanguageGLSL = 2,
SourceLanguageOpenCL_C = 3,
SourceLanguageOpenCL_CPP = 4,
SourceLanguageHLSL = 5,
SourceLanguageMax = 0x7fffffff,
};
enum ExecutionModel {
@ -71,18 +73,21 @@ enum ExecutionModel {
ExecutionModelFragment = 4,
ExecutionModelGLCompute = 5,
ExecutionModelKernel = 6,
ExecutionModelMax = 0x7fffffff,
};
enum AddressingModel {
AddressingModelLogical = 0,
AddressingModelPhysical32 = 1,
AddressingModelPhysical64 = 2,
AddressingModelMax = 0x7fffffff,
};
enum MemoryModel {
MemoryModelSimple = 0,
MemoryModelGLSL450 = 1,
MemoryModelOpenCL = 2,
MemoryModelMax = 0x7fffffff,
};
enum ExecutionMode {
@ -117,6 +122,7 @@ enum ExecutionMode {
ExecutionModeOutputTriangleStrip = 29,
ExecutionModeVecTypeHint = 30,
ExecutionModeContractionOff = 31,
ExecutionModeMax = 0x7fffffff,
};
enum StorageClass {
@ -132,6 +138,8 @@ enum StorageClass {
StorageClassPushConstant = 9,
StorageClassAtomicCounter = 10,
StorageClassImage = 11,
StorageClassStorageBuffer = 12,
StorageClassMax = 0x7fffffff,
};
enum Dim {
@ -142,6 +150,7 @@ enum Dim {
DimRect = 4,
DimBuffer = 5,
DimSubpassData = 6,
DimMax = 0x7fffffff,
};
enum SamplerAddressingMode {
@ -150,11 +159,13 @@ enum SamplerAddressingMode {
SamplerAddressingModeClamp = 2,
SamplerAddressingModeRepeat = 3,
SamplerAddressingModeRepeatMirrored = 4,
SamplerAddressingModeMax = 0x7fffffff,
};
enum SamplerFilterMode {
SamplerFilterModeNearest = 0,
SamplerFilterModeLinear = 1,
SamplerFilterModeMax = 0x7fffffff,
};
enum ImageFormat {
@ -198,6 +209,7 @@ enum ImageFormat {
ImageFormatRg8ui = 37,
ImageFormatR16ui = 38,
ImageFormatR8ui = 39,
ImageFormatMax = 0x7fffffff,
};
enum ImageChannelOrder {
@ -221,6 +233,7 @@ enum ImageChannelOrder {
ImageChannelOrdersRGBA = 17,
ImageChannelOrdersBGRA = 18,
ImageChannelOrderABGR = 19,
ImageChannelOrderMax = 0x7fffffff,
};
enum ImageChannelDataType {
@ -241,6 +254,7 @@ enum ImageChannelDataType {
ImageChannelDataTypeFloat = 14,
ImageChannelDataTypeUnormInt24 = 15,
ImageChannelDataTypeUnormInt101010_2 = 16,
ImageChannelDataTypeMax = 0x7fffffff,
};
enum ImageOperandsShift {
@ -252,6 +266,7 @@ enum ImageOperandsShift {
ImageOperandsConstOffsetsShift = 5,
ImageOperandsSampleShift = 6,
ImageOperandsMinLodShift = 7,
ImageOperandsMax = 0x7fffffff,
};
enum ImageOperandsMask {
@ -272,6 +287,7 @@ enum FPFastMathModeShift {
FPFastMathModeNSZShift = 2,
FPFastMathModeAllowRecipShift = 3,
FPFastMathModeFastShift = 4,
FPFastMathModeMax = 0x7fffffff,
};
enum FPFastMathModeMask {
@ -288,17 +304,20 @@ enum FPRoundingMode {
FPRoundingModeRTZ = 1,
FPRoundingModeRTP = 2,
FPRoundingModeRTN = 3,
FPRoundingModeMax = 0x7fffffff,
};
enum LinkageType {
LinkageTypeExport = 0,
LinkageTypeImport = 1,
LinkageTypeMax = 0x7fffffff,
};
enum AccessQualifier {
AccessQualifierReadOnly = 0,
AccessQualifierWriteOnly = 1,
AccessQualifierReadWrite = 2,
AccessQualifierMax = 0x7fffffff,
};
enum FunctionParameterAttribute {
@ -310,6 +329,7 @@ enum FunctionParameterAttribute {
FunctionParameterAttributeNoCapture = 5,
FunctionParameterAttributeNoWrite = 6,
FunctionParameterAttributeNoReadWrite = 7,
FunctionParameterAttributeMax = 0x7fffffff,
};
enum Decoration {
@ -356,6 +376,11 @@ enum Decoration {
DecorationNoContraction = 42,
DecorationInputAttachmentIndex = 43,
DecorationAlignment = 44,
DecorationOverrideCoverageNV = 5248,
DecorationPassthroughNV = 5250,
DecorationViewportRelativeNV = 5252,
DecorationSecondaryViewportRelativeNV = 5256,
DecorationMax = 0x7fffffff,
};
enum BuiltIn {
@ -400,11 +425,28 @@ enum BuiltIn {
BuiltInSubgroupLocalInvocationId = 41,
BuiltInVertexIndex = 42,
BuiltInInstanceIndex = 43,
BuiltInSubgroupEqMaskKHR = 4416,
BuiltInSubgroupGeMaskKHR = 4417,
BuiltInSubgroupGtMaskKHR = 4418,
BuiltInSubgroupLeMaskKHR = 4419,
BuiltInSubgroupLtMaskKHR = 4420,
BuiltInBaseVertex = 4424,
BuiltInBaseInstance = 4425,
BuiltInDrawIndex = 4426,
BuiltInDeviceIndex = 4438,
BuiltInViewIndex = 4440,
BuiltInViewportMaskNV = 5253,
BuiltInSecondaryPositionNV = 5257,
BuiltInSecondaryViewportMaskNV = 5258,
BuiltInPositionPerViewNV = 5261,
BuiltInViewportMaskPerViewNV = 5262,
BuiltInMax = 0x7fffffff,
};
enum SelectionControlShift {
SelectionControlFlattenShift = 0,
SelectionControlDontFlattenShift = 1,
SelectionControlMax = 0x7fffffff,
};
enum SelectionControlMask {
@ -416,6 +458,7 @@ enum SelectionControlMask {
enum LoopControlShift {
LoopControlUnrollShift = 0,
LoopControlDontUnrollShift = 1,
LoopControlMax = 0x7fffffff,
};
enum LoopControlMask {
@ -429,6 +472,7 @@ enum FunctionControlShift {
FunctionControlDontInlineShift = 1,
FunctionControlPureShift = 2,
FunctionControlConstShift = 3,
FunctionControlMax = 0x7fffffff,
};
enum FunctionControlMask {
@ -450,6 +494,7 @@ enum MemorySemanticsShift {
MemorySemanticsCrossWorkgroupMemoryShift = 9,
MemorySemanticsAtomicCounterMemoryShift = 10,
MemorySemanticsImageMemoryShift = 11,
MemorySemanticsMax = 0x7fffffff,
};
enum MemorySemanticsMask {
@ -470,6 +515,7 @@ enum MemoryAccessShift {
MemoryAccessVolatileShift = 0,
MemoryAccessAlignedShift = 1,
MemoryAccessNontemporalShift = 2,
MemoryAccessMax = 0x7fffffff,
};
enum MemoryAccessMask {
@ -485,22 +531,26 @@ enum Scope {
ScopeWorkgroup = 2,
ScopeSubgroup = 3,
ScopeInvocation = 4,
ScopeMax = 0x7fffffff,
};
enum GroupOperation {
GroupOperationReduce = 0,
GroupOperationInclusiveScan = 1,
GroupOperationExclusiveScan = 2,
GroupOperationMax = 0x7fffffff,
};
enum KernelEnqueueFlags {
KernelEnqueueFlagsNoWait = 0,
KernelEnqueueFlagsWaitKernel = 1,
KernelEnqueueFlagsWaitWorkGroup = 2,
KernelEnqueueFlagsMax = 0x7fffffff,
};
enum KernelProfilingInfoShift {
KernelProfilingInfoCmdExecTimeShift = 0,
KernelProfilingInfoMax = 0x7fffffff,
};
enum KernelProfilingInfoMask {
@ -565,6 +615,26 @@ enum Capability {
CapabilityStorageImageReadWithoutFormat = 55,
CapabilityStorageImageWriteWithoutFormat = 56,
CapabilityMultiViewport = 57,
CapabilitySubgroupBallotKHR = 4423,
CapabilityDrawParameters = 4427,
CapabilitySubgroupVoteKHR = 4431,
CapabilityStorageBuffer16BitAccess = 4433,
CapabilityStorageUniformBufferBlock16 = 4433,
CapabilityStorageUniform16 = 4434,
CapabilityUniformAndStorageBuffer16BitAccess = 4434,
CapabilityStoragePushConstant16 = 4435,
CapabilityStorageInputOutput16 = 4436,
CapabilityDeviceGroup = 4437,
CapabilityMultiView = 4439,
CapabilityVariablePointersStorageBuffer = 4441,
CapabilityVariablePointers = 4442,
CapabilitySampleMaskOverrideCoverageNV = 5249,
CapabilityGeometryShaderPassthroughNV = 5251,
CapabilityShaderViewportIndexLayerNV = 5254,
CapabilityShaderViewportMaskNV = 5255,
CapabilityShaderStereoViewNV = 5259,
CapabilityPerViewAttributesNV = 5260,
CapabilityMax = 0x7fffffff,
};
enum Op {
@ -862,6 +932,13 @@ enum Op {
OpAtomicFlagTestAndSet = 318,
OpAtomicFlagClear = 319,
OpImageSparseRead = 320,
OpSubgroupBallotKHR = 4421,
OpSubgroupFirstInvocationKHR = 4422,
OpSubgroupAllKHR = 4428,
OpSubgroupAnyKHR = 4429,
OpSubgroupAllEqualKHR = 4430,
OpSubgroupReadInvocationKHR = 4432,
OpMax = 0x7fffffff,
};
// Overload operator| for mask bit combining

View File

@ -186,6 +186,7 @@ enum Types
TypeExtension,
TypeExpression,
TypeConstantOp,
TypeCombinedImageSampler,
TypeUndef
};
@ -202,6 +203,25 @@ struct SPIRUndef : IVariant
uint32_t basetype;
};
// This type is only used by backends which need to access the combined image and sampler IDs separately after
// the OpSampledImage opcode.
struct SPIRCombinedImageSampler : IVariant
{
enum
{
type = TypeCombinedImageSampler
};
SPIRCombinedImageSampler(uint32_t type_, uint32_t image_, uint32_t sampler_)
: combined_type(type_)
, image(image_)
, sampler(sampler_)
{
}
uint32_t combined_type;
uint32_t image;
uint32_t sampler;
};
struct SPIRConstantOp : IVariant
{
enum
@ -557,6 +577,7 @@ struct SPIRFunction : IVariant
uint32_t sampler_id;
bool global_image;
bool global_sampler;
bool depth;
};
uint32_t return_type;
@ -950,6 +971,14 @@ struct Meta
uint32_t sampler = 0;
std::unordered_map<uint32_t, uint32_t> decoration_word_offset;
// Used when the parser has detected a candidate identifier which matches
// known "magic" counter buffers as emitted by HLSL frontends.
// We will need to match the identifiers by name later when reflecting resources.
// We could use the regular alias later, but the alias will be mangled when parsing SPIR-V because the identifier
// is not a valid identifier in any high-level language.
std::string hlsl_magic_counter_buffer_name;
bool hlsl_magic_counter_buffer_candidate = false;
};
// A user callback that remaps the type of any variable.

View File

@ -356,6 +356,9 @@ const SPIRType &Compiler::expression_type(uint32_t id) const
case TypeUndef:
return get<SPIRType>(get<SPIRUndef>(id).basetype);
case TypeCombinedImageSampler:
return get<SPIRType>(get<SPIRCombinedImageSampler>(id).combined_type);
default:
SPIRV_CROSS_THROW("Cannot resolve expression type.");
}
@ -819,6 +822,21 @@ void Compiler::set_name(uint32_t id, const std::string &name)
if (name.empty())
return;
// glslang uses identifiers to pass along meaningful information
// about HLSL reflection.
auto &m = meta.at(id);
if (source.hlsl && name.size() >= 6 && name.find("@count") == name.size() - 6)
{
m.hlsl_magic_counter_buffer_candidate = true;
m.hlsl_magic_counter_buffer_name = name.substr(0, name.find("@count"));
}
else
{
m.hlsl_magic_counter_buffer_candidate = false;
m.hlsl_magic_counter_buffer_name.clear();
}
// Reserved for temporaries.
if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
return;
@ -1155,12 +1173,22 @@ void Compiler::parse(const Instruction &instruction)
source.es = true;
source.version = ops[1];
source.known = true;
source.hlsl = false;
break;
case SourceLanguageGLSL:
source.es = false;
source.version = ops[1];
source.known = true;
source.hlsl = false;
break;
case SourceLanguageHLSL:
// For purposes of cross-compiling, this is GLSL 450.
source.es = false;
source.version = 450;
source.known = true;
source.hlsl = true;
break;
default:
@ -2572,7 +2600,7 @@ bool Compiler::CombinedImageSamplerHandler::end_function_scope(const uint32_t *a
if (s)
sampler_id = s->self;
register_combined_image_sampler(caller, image_id, sampler_id);
register_combined_image_sampler(caller, image_id, sampler_id, param.depth);
}
}
@ -2580,13 +2608,13 @@ bool Compiler::CombinedImageSamplerHandler::end_function_scope(const uint32_t *a
}
void Compiler::CombinedImageSamplerHandler::register_combined_image_sampler(SPIRFunction &caller, uint32_t image_id,
uint32_t sampler_id)
uint32_t sampler_id, bool depth)
{
// We now have a texture ID and a sampler ID which will either be found as a global
// or a parameter in our own function. If both are global, they will not need a parameter,
// otherwise, add it to our list.
SPIRFunction::CombinedImageSamplerParameter param = {
0u, image_id, sampler_id, true, true,
0u, image_id, sampler_id, true, true, depth,
};
auto texture_itr = find_if(begin(caller.arguments), end(caller.arguments),
@ -2630,6 +2658,7 @@ void Compiler::CombinedImageSamplerHandler::register_combined_image_sampler(SPIR
type.basetype = SPIRType::SampledImage;
type.pointer = false;
type.storage = StorageClassGeneric;
type.image.depth = depth;
ptr_type = type;
ptr_type.pointer = true;
@ -2696,11 +2725,12 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
bool separate_image = type.basetype == SPIRType::Image && type.image.sampled == 1;
bool separate_sampler = type.basetype == SPIRType::Sampler;
if (separate_image)
SPIRV_CROSS_THROW(
"Attempting to use arrays of separate images. This is not possible to statically remap to plain GLSL.");
SPIRV_CROSS_THROW("Attempting to use arrays or structs of separate images. This is not possible to "
"statically remap to plain GLSL.");
if (separate_sampler)
SPIRV_CROSS_THROW("Attempting to use arrays of separate samplers. This is not possible to statically "
"remap to plain GLSL.");
SPIRV_CROSS_THROW(
"Attempting to use arrays or structs of separate samplers. This is not possible to statically "
"remap to plain GLSL.");
return true;
}
@ -2733,7 +2763,8 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
if (sampler)
sampler_id = sampler->self;
register_combined_image_sampler(callee, image_id, sampler_id);
auto &combined_type = compiler.get<SPIRType>(args[0]);
register_combined_image_sampler(callee, image_id, sampler_id, combined_type.image.depth);
}
}
@ -3350,3 +3381,105 @@ void Compiler::update_active_builtins()
ActiveBuiltinHandler handler(*this);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
}
void Compiler::analyze_sampler_comparison_states()
{
CombinedImageSamplerUsageHandler handler(*this);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
comparison_samplers = move(handler.comparison_samplers);
}
bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint32_t *args, uint32_t length)
{
if (length < 3)
return false;
auto &func = compiler.get<SPIRFunction>(args[2]);
const auto *arg = &args[3];
length -= 3;
for (uint32_t i = 0; i < length; i++)
{
auto &argument = func.arguments[i];
dependency_hierarchy[argument.id].insert(arg[i]);
}
return true;
}
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_samplers(uint32_t sampler)
{
// Traverse the variable dependency hierarchy and tag everything in its path with comparison samplers.
comparison_samplers.insert(sampler);
for (auto &samp : dependency_hierarchy[sampler])
add_hierarchy_to_comparison_samplers(samp);
}
bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
{
switch (opcode)
{
case OpAccessChain:
case OpInBoundsAccessChain:
case OpLoad:
{
if (length < 3)
return false;
dependency_hierarchy[args[1]].insert(args[2]);
break;
}
case OpSampledImage:
{
if (length < 4)
return false;
uint32_t result_type = args[0];
auto &type = compiler.get<SPIRType>(result_type);
if (type.image.depth)
{
// This sampler must be a SamplerComparisionState, and not a regular SamplerState.
uint32_t sampler = args[3];
add_hierarchy_to_comparison_samplers(sampler);
}
return true;
}
default:
break;
}
return true;
}
bool Compiler::buffer_is_hlsl_counter_buffer(uint32_t id) const
{
if (meta.at(id).hlsl_magic_counter_buffer_candidate)
{
auto *var = maybe_get<SPIRVariable>(id);
// Ensure that this is actually a buffer object.
return var && has_decoration(get<SPIRType>(var->basetype).self, DecorationBufferBlock);
}
else
return false;
}
bool Compiler::buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const
{
auto &name = get_name(id);
uint32_t id_bound = get_current_id_bound();
for (uint32_t i = 0; i < id_bound; i++)
{
if (meta[i].hlsl_magic_counter_buffer_candidate && meta[i].hlsl_magic_counter_buffer_name == name)
{
auto *var = maybe_get<SPIRVariable>(i);
// Ensure that this is actually a buffer object.
if (var && has_decoration(get<SPIRType>(var->basetype).self, DecorationBufferBlock))
{
counter_id = i;
return true;
}
}
}
return false;
}

View File

@ -335,6 +335,25 @@ public:
// If the decoration does not have any value attached to it (e.g. DecorationRelaxedPrecision), this function will also return false.
bool get_binary_offset_for_decoration(uint32_t id, spv::Decoration decoration, uint32_t &word_offset) const;
// HLSL counter buffer reflection interface.
// Append/Consume/Increment/Decrement in HLSL is implemented as two "neighbor" buffer objects where
// one buffer implements the storage, and a single buffer containing just a lone "int" implements the counter.
// To SPIR-V these will be exposed as two separate buffers, but glslang HLSL frontend emits a special indentifier
// which lets us link the two buffers together.
// Queries if a variable ID is a counter buffer which "belongs" to a regular buffer object.
// NOTE: This query is purely based on OpName identifiers as found in the SPIR-V module, and will
// only return true if OpSource was reported HLSL.
// To rely on this functionality, ensure that the SPIR-V module is not stripped.
bool buffer_is_hlsl_counter_buffer(uint32_t id) const;
// Queries if a buffer object has a neighbor "counter" buffer.
// If so, the ID of that counter buffer will be returned in counter_id.
// NOTE: This query is purely based on OpName identifiers as found in the SPIR-V module, and will
// only return true if OpSource was reported HLSL.
// To rely on this functionality, ensure that the SPIR-V module is not stripped.
bool buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const;
protected:
const uint32_t *stream(const Instruction &instr) const
{
@ -413,6 +432,7 @@ protected:
uint32_t version = 0;
bool es = false;
bool known = false;
bool hlsl = false;
Source() = default;
} source;
@ -582,7 +602,8 @@ protected:
uint32_t remap_parameter(uint32_t id);
void push_remap_parameters(const SPIRFunction &func, const uint32_t *args, uint32_t length);
void pop_remap_parameters();
void register_combined_image_sampler(SPIRFunction &caller, uint32_t texture_id, uint32_t sampler_id);
void register_combined_image_sampler(SPIRFunction &caller, uint32_t texture_id, uint32_t sampler_id,
bool depth);
};
struct ActiveBuiltinHandler : OpcodeHandler
@ -619,6 +640,29 @@ protected:
void analyze_parameter_preservation(
SPIRFunction &entry, const CFG &cfg,
const std::unordered_map<uint32_t, std::unordered_set<uint32_t>> &variable_to_blocks);
// If a variable ID or parameter ID is found in this set, a sampler is actually a shadow/comparison sampler.
// SPIR-V does not support this distinction, so we must keep track of this information outside the type system.
// There might be unrelated IDs found in this set which do not correspond to actual variables.
// This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs.
std::unordered_set<uint32_t> comparison_samplers;
void analyze_sampler_comparison_states();
struct CombinedImageSamplerUsageHandler : OpcodeHandler
{
CombinedImageSamplerUsageHandler(Compiler &compiler_)
: compiler(compiler_)
{
}
bool begin_function_scope(const uint32_t *args, uint32_t length) override;
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> dependency_hierarchy;
std::unordered_set<uint32_t> comparison_samplers;
void add_hierarchy_to_comparison_samplers(uint32_t sampler);
};
};
}

View File

@ -311,6 +311,7 @@ string CompilerGLSL::compile()
find_static_extensions();
fixup_image_load_store_access();
update_active_builtins();
analyze_sampler_comparison_states();
uint32_t pass_count = 0;
do
@ -1837,6 +1838,14 @@ string CompilerGLSL::to_expression(uint32_t id)
}
}
case TypeCombinedImageSampler:
// This type should never be taken the expression of directly.
// The intention is that texture sampling functions will extract the image and samplers
// separately and take their expressions as needed.
// GLSL does not use this type because OpSampledImage immediately creates a combined image sampler
// expression ala sampler2D(texture, sampler).
SPIRV_CROSS_THROW("Combined image samplers have no default expression representation.");
default:
return to_name(id);
}
@ -5810,7 +5819,6 @@ string CompilerGLSL::to_qualifiers_glsl(uint32_t id)
string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
{
// glslangValidator seems to make all arguments pointer no matter what which is rather bizarre ...
// Not sure if argument being pointer type should make the argument inout.
auto &type = expression_type(arg.id);
const char *direction = "";
@ -5822,14 +5830,37 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
direction = "out ";
}
return join(direction, to_qualifiers_glsl(arg.id), variable_decl(type, to_name(arg.id)));
// We need some special consideration for samplers.
// The shadow qualifier for a sampler does not exist in SPIR-V, so the type might depend on which variable this is.
SPIRType fake_type;
const auto *tmp_type = &type;
if (type.basetype == SPIRType::Sampler)
{
tmp_type = &fake_type;
fake_type = type;
fake_type.image.depth = comparison_samplers.count(arg.id) != 0;
}
return join(direction, to_qualifiers_glsl(arg.id), variable_decl(*tmp_type, to_name(arg.id)));
}
string CompilerGLSL::variable_decl(const SPIRVariable &variable)
{
// Ignore the pointer type since GLSL doesn't have pointers.
auto &type = get<SPIRType>(variable.basetype);
auto res = join(to_qualifiers_glsl(variable.self), variable_decl(type, to_name(variable.self)));
// We need some special consideration for samplers.
// The shadow qualifier for a sampler does not exist in SPIR-V, so the type might depend on which variable this is.
SPIRType fake_type;
const auto *tmp_type = &type;
if (type.basetype == SPIRType::Sampler)
{
tmp_type = &fake_type;
fake_type = type;
fake_type.image.depth = comparison_samplers.count(variable.self) != 0;
}
auto res = join(to_qualifiers_glsl(variable.self), variable_decl(*tmp_type, to_name(variable.self)));
if (variable.loop_variable)
res += join(" = ", to_expression(variable.static_expression));
else if (variable.initializer)
@ -6009,7 +6040,11 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type)
return image_type_glsl(type);
case SPIRType::Sampler:
return "sampler";
// This is a hacky workaround. The sampler type in SPIR-V doesn't actually signal this distinction,
// but in higher level code we need it.
// The depth field is set by calling code based on the variable ID of the sampler, effectively reintroducing
// this distinction into the type system.
return type.image.depth ? "samplerShadow" : "sampler";
case SPIRType::Void:
return "void";

View File

@ -366,7 +366,7 @@ protected:
uint64_t combined_decoration_for_member(const SPIRType &type, uint32_t index);
std::string layout_for_variable(const SPIRVariable &variable);
std::string to_combined_image_sampler(uint32_t image_id, uint32_t samp_id);
bool skip_argument(uint32_t id) const;
virtual bool skip_argument(uint32_t id) const;
bool ssbo_is_std430_packing(const SPIRType &type);
uint32_t type_to_std430_base_size(const SPIRType &type);

View File

@ -43,7 +43,41 @@ static bool opcode_is_sign_invariant(Op opcode)
}
}
string CompilerHLSL::image_type_hlsl(const SPIRType &type)
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
{
auto &imagetype = get<SPIRType>(type.image.type);
const char *dim = nullptr;
switch (type.image.dim)
{
case Dim1D:
dim = "1D";
break;
case Dim2D:
dim = "2D";
break;
case Dim3D:
dim = "3D";
break;
case DimCube:
dim = "Cube";
break;
case DimRect:
SPIRV_CROSS_THROW("Rectangle texture support is not yet implemented for HLSL"); // TODO
case DimBuffer:
// Buffer/RWBuffer.
SPIRV_CROSS_THROW("Buffer/RWBuffer support is not yet implemented for HLSL"); // TODO
case DimSubpassData:
// This should be implemented same way as desktop GL. Fetch on a 2D texture based on int2(SV_Position).
SPIRV_CROSS_THROW("Subpass data support is not yet implemented for HLSL"); // TODO
default:
SPIRV_CROSS_THROW("Invalid dimension.");
}
uint32_t components = 4;
const char *arrayed = type.image.arrayed ? "Array" : "";
return join("Texture", dim, arrayed, "<", type_to_glsl(imagetype), components, ">");
}
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
{
auto &imagetype = get<SPIRType>(type.image.type);
string res;
@ -105,17 +139,21 @@ string CompilerHLSL::image_type_hlsl(const SPIRType &type)
if (type.image.ms)
res += "MS";
if (type.image.arrayed)
{
if (is_legacy_desktop())
require_extension("GL_EXT_texture_array");
res += "Array";
}
if (type.image.depth)
res += "Shadow";
return res;
}
string CompilerHLSL::image_type_hlsl(const SPIRType &type)
{
if (options.shader_model <= 30)
return image_type_hlsl_legacy(type);
else
return image_type_hlsl_modern(type);
}
string CompilerHLSL::type_to_glsl(const SPIRType &type)
{
// Ignore the pointer type since GLSL doesn't have pointers.
@ -134,7 +172,7 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type)
return image_type_hlsl(type);
case SPIRType::Sampler:
return "sampler";
return type.image.depth ? "SamplerComparisonState" : "SamplerState";
case SPIRType::Void:
return "void";
@ -856,6 +894,39 @@ void CompilerHLSL::emit_push_constant_block(const SPIRVariable &)
statement("constant block");
}
string CompilerHLSL::to_sampler_expression(uint32_t id)
{
return join("_", to_expression(id), "_sampler");
}
void CompilerHLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id)
{
set<SPIRCombinedImageSampler>(result_id, result_type, image_id, samp_id);
}
string CompilerHLSL::to_func_call_arg(uint32_t id)
{
string arg_str = CompilerGLSL::to_func_call_arg(id);
if (options.shader_model <= 30)
return arg_str;
// Manufacture automatic sampler arg if the arg is a SampledImage texture and we're in modern HLSL.
auto *var = maybe_get<SPIRVariable>(id);
if (var)
{
auto &type = get<SPIRType>(var->basetype);
// We don't have to consider combined image samplers here via OpSampledImage because
// those variables cannot be passed as arguments to functions.
// Only global SampledImage variables may be used as arguments.
if (type.basetype == SPIRType::SampledImage)
arg_str += ", " + to_sampler_expression(id);
}
return arg_str;
}
void CompilerHLSL::emit_function_prototype(SPIRFunction &func, uint64_t return_flags)
{
auto &execution = get_entry_point();
@ -894,6 +965,18 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, uint64_t return_f
add_local_variable_name(arg.id);
decl += argument_decl(arg);
// Flatten a combined sampler to two separate arguments in modern HLSL.
auto &arg_type = get<SPIRType>(arg.type);
if (options.shader_model > 30 && arg_type.basetype == SPIRType::SampledImage)
{
// Manufacture automatic sampler arg for SampledImage texture
decl += ", ";
if (arg_type.basetype == SPIRType::SampledImage)
decl += join(arg_type.image.depth ? "SamplerComparisonState " : "SamplerState ",
to_sampler_expression(arg.id));
}
if (&arg != &func.arguments.back())
decl += ", ";
@ -1127,6 +1210,8 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
bool gather = false;
bool proj = false;
const uint32_t *opt = nullptr;
auto *combined_image = maybe_get<SPIRCombinedImageSampler>(img);
auto img_expr = to_expression(combined_image ? combined_image->image : img);
switch (op)
{
@ -1244,7 +1329,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
{
SPIRV_CROSS_THROW("texelFetch is not supported in HLSL shader model 2/3.");
}
texop += to_expression(img);
texop += img_expr;
texop += ".Load";
}
else
@ -1257,7 +1342,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
if (options.shader_model >= 40)
{
texop += to_expression(img);
texop += img_expr;
if (imgtype.image.depth)
texop += ".SampleCmp";
@ -1292,6 +1377,8 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
case DimBuffer:
case DimSubpassData:
SPIRV_CROSS_THROW("Buffer texture support is not yet implemented for HLSL"); // TODO
default:
SPIRV_CROSS_THROW("Invalid dimension.");
}
if (gather)
@ -1311,21 +1398,17 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
expr += texop;
expr += "(";
if (op != OpImageFetch)
if (op != OpImageFetch && (options.shader_model >= 40))
{
if (options.shader_model >= 40)
{
expr += "_";
}
expr += to_expression(img);
if (options.shader_model >= 40)
{
expr += "_sampler";
}
string sampler_expr;
if (combined_image)
sampler_expr = to_expression(combined_image->sampler);
else
sampler_expr = to_sampler_expression(img);
expr += sampler_expr;
}
bool swizz_func = backend.swizzle_is_function;
auto swizzle = [swizz_func](uint32_t comps, uint32_t in_comps) -> const char * {
auto swizzle = [](uint32_t comps, uint32_t in_comps) -> const char * {
if (comps == in_comps)
return "";
@ -1334,9 +1417,9 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
case 1:
return ".x";
case 2:
return swizz_func ? ".xy()" : ".xy";
return ".xy";
case 3:
return swizz_func ? ".xyz()" : ".xyz";
return ".xyz";
default:
return "";
}
@ -1382,9 +1465,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
if (op == OpImageFetch)
{
auto &coordtype = expression_type(coord);
stringstream str;
str << coordtype.vecsize + 1;
coord_expr = "int" + str.str() + "(" + coord_expr + ", " + to_expression(lod) + ")";
coord_expr = join("int", coordtype.vecsize + 1, "(", coord_expr, ", ", to_expression(lod), ")");
}
if (op != OpImageFetch)
@ -1455,46 +1536,62 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
emit_op(result_type, id, expr, forward, false);
}
void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
{
auto &type = get<SPIRType>(var.basetype);
switch (type.basetype)
{
case SPIRType::SampledImage:
case SPIRType::Image:
{
statement(image_type_hlsl_modern(type), " ", to_name(var.self), ";");
if (type.basetype == SPIRType::SampledImage)
{
// For combined image samplers, also emit a combined image sampler.
if (type.image.depth)
statement("SamplerComparisonState ", to_sampler_expression(var.self), ";");
else
statement("SamplerState ", to_sampler_expression(var.self), ";");
}
break;
}
case SPIRType::Sampler:
if (comparison_samplers.count(var.self))
statement("SamplerComparisonState ", to_name(var.self), ";");
else
statement("SamplerState ", to_name(var.self), ";");
break;
default:
statement(variable_decl(var), ";");
break;
}
}
void CompilerHLSL::emit_legacy_uniform(const SPIRVariable &var)
{
auto &type = get<SPIRType>(var.basetype);
switch (type.basetype)
{
case SPIRType::Sampler:
case SPIRType::Image:
SPIRV_CROSS_THROW("Separate image and samplers not supported in legacy HLSL.");
default:
statement(variable_decl(var), ";");
break;
}
}
void CompilerHLSL::emit_uniform(const SPIRVariable &var)
{
add_resource_name(var.self);
auto &type = get<SPIRType>(var.basetype);
if (options.shader_model >= 40 && type.basetype == SPIRType::SampledImage)
{
auto &imagetype = get<SPIRType>(type.image.type);
string dim;
switch (type.image.dim)
{
case Dim1D:
dim = "1D";
break;
case Dim2D:
dim = "2D";
break;
case Dim3D:
dim = "3D";
break;
case DimCube:
dim = "Cube";
break;
case DimRect:
case DimBuffer:
case DimSubpassData:
SPIRV_CROSS_THROW("Buffer texture support is not yet implemented for HLSL"); // TODO
}
string arrayed = type.image.arrayed ? "Array" : "";
statement("Texture", dim, arrayed, "<", type_to_glsl(imagetype), "4> ", to_name(var.self), ";");
if (type.image.depth)
statement("SamplerComparisonState _", to_name(var.self), "_sampler;");
else
statement("SamplerState _", to_name(var.self), "_sampler;");
}
if (options.shader_model >= 40)
emit_modern_uniform(var);
else
{
statement(variable_decl(var), ";");
}
// TODO: Separate samplers/images
emit_legacy_uniform(var);
}
string CompilerHLSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in_type)
@ -1845,6 +1942,7 @@ string CompilerHLSL::compile()
backend.boolean_mix_support = false;
update_active_builtins();
analyze_sampler_comparison_states();
uint32_t pass_count = 0;
do

View File

@ -61,6 +61,8 @@ public:
private:
std::string type_to_glsl(const SPIRType &type) override;
std::string image_type_hlsl(const SPIRType &type);
std::string image_type_hlsl_modern(const SPIRType &type);
std::string image_type_hlsl_legacy(const SPIRType &type);
void emit_function_prototype(SPIRFunction &func, uint64_t return_flags) override;
void emit_hlsl_entry_point();
void emit_header() override;
@ -76,9 +78,14 @@ private:
void emit_buffer_block(const SPIRVariable &type) override;
void emit_push_constant_block(const SPIRVariable &var) override;
void emit_uniform(const SPIRVariable &var) override;
void emit_modern_uniform(const SPIRVariable &var);
void emit_legacy_uniform(const SPIRVariable &var);
std::string layout_for_member(const SPIRType &type, uint32_t index) override;
std::string to_interpolation_qualifiers(uint64_t flags) override;
std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;
std::string to_func_call_arg(uint32_t id) override;
std::string to_sampler_expression(uint32_t id);
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override;

View File

@ -2777,6 +2777,11 @@ size_t CompilerMSL::get_declared_type_alignment(uint32_t type_id, uint64_t dec_m
}
}
bool CompilerMSL::skip_argument(uint32_t) const
{
return false;
}
bool CompilerMSL::OpCodePreprocessor::handle(Op opcode, const uint32_t *args, uint32_t /*length*/)
{
// Since MSL exists in a single execution scope, function prototype declarations are not

View File

@ -218,6 +218,7 @@ protected:
bool op1_is_pointer = false, uint32_t op2 = 0);
const char *get_memory_order(uint32_t spv_mem_sem);
void add_pragma_line(const std::string &line);
bool skip_argument(uint32_t id) const override;
Options options;
std::unordered_map<std::string, std::string> func_name_overrides;