mirror of
https://github.com/KhronosGroup/SPIRV-Cross.git
synced 2024-11-09 22:00:05 +00:00
Merge with upstream
This commit is contained in:
commit
d677e63860
9
main.cpp
9
main.cpp
@ -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");
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
31
shaders-hlsl/frag/combined-texture-sampler-parameter.frag
Normal file
31
shaders-hlsl/frag/combined-texture-sampler-parameter.frag
Normal 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);
|
||||
}
|
29
shaders-hlsl/frag/combined-texture-sampler-shadow.frag
Normal file
29
shaders-hlsl/frag/combined-texture-sampler-shadow.frag
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
16
shaders-msl/frag/separate-image-sampler-argument.frag
Normal file
16
shaders-msl/frag/separate-image-sampler-argument.frag
Normal 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);
|
||||
}
|
29
shaders/vulkan/frag/combined-texture-sampler-shadow.vk.frag
Normal file
29
shaders/vulkan/frag/combined-texture-sampler-shadow.vk.frag
Normal 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);
|
||||
}
|
83
spirv.hpp
83
spirv.hpp
@ -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
|
||||
|
@ -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.
|
||||
|
149
spirv_cross.cpp
149
spirv_cross.cpp
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
220
spirv_hlsl.cpp
220
spirv_hlsl.cpp
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user