Merge pull request #284 from KhronosGroup/fix-283

Implement texture query APIs in HLSL
This commit is contained in:
Hans-Kristian Arntzen 2017-09-20 15:11:33 +02:00 committed by GitHub
commit 7170864159
10 changed files with 727 additions and 14 deletions

View File

@ -0,0 +1,145 @@
Texture1D<uint4> uSampler1DUint : register(t0);
SamplerState _uSampler1DUint_sampler : register(s0);
Texture1D<int4> uSampler1DInt : register(t0);
SamplerState _uSampler1DInt_sampler : register(s0);
Texture1D<float4> uSampler1DFloat : register(t0);
SamplerState _uSampler1DFloat_sampler : register(s0);
Texture2DArray<int4> uSampler2DArray : register(t2);
SamplerState _uSampler2DArray_sampler : register(s2);
Texture3D<float4> uSampler3D : register(t3);
SamplerState _uSampler3D_sampler : register(s3);
TextureCube<float4> uSamplerCube : register(t4);
SamplerState _uSamplerCube_sampler : register(s4);
TextureCubeArray<uint4> uSamplerCubeArray : register(t5);
SamplerState _uSamplerCubeArray_sampler : register(s5);
Buffer<float4> uSamplerBuffer : register(t6);
Texture2DMS<int4> uSamplerMS : register(t7);
SamplerState _uSamplerMS_sampler : register(s7);
Texture2DMSArray<float4> uSamplerMSArray : register(t8);
SamplerState _uSamplerMSArray_sampler : register(s8);
Texture2D<float4> uSampler2D : register(t1);
SamplerState _uSampler2D_sampler : register(s1);
uint SPIRV_Cross_textureSize(Texture1D<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Texture1D<int4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Texture1D<uint4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2D<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DArray<int4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture3D<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Buffer<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(ret.x);
return ret;
}
uint2 SPIRV_Cross_textureSize(TextureCube<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(TextureCubeArray<uint4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2DMS<int4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DMSArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(ret.x, ret.y, ret.z, Param);
return ret;
}
void frag_main()
{
uint _17_dummy_parameter;
int a = int(SPIRV_Cross_textureSize(uSampler1DUint, uint(0), _17_dummy_parameter));
uint _24_dummy_parameter;
a = int(SPIRV_Cross_textureSize(uSampler1DInt, uint(0), _24_dummy_parameter));
uint _32_dummy_parameter;
a = int(SPIRV_Cross_textureSize(uSampler1DFloat, uint(0), _32_dummy_parameter));
uint _42_dummy_parameter;
int3 c = int3(SPIRV_Cross_textureSize(uSampler2DArray, uint(0), _42_dummy_parameter));
uint _50_dummy_parameter;
int3 d = int3(SPIRV_Cross_textureSize(uSampler3D, uint(0), _50_dummy_parameter));
uint _60_dummy_parameter;
int2 e = int2(SPIRV_Cross_textureSize(uSamplerCube, uint(0), _60_dummy_parameter));
uint _68_dummy_parameter;
int3 f = int3(SPIRV_Cross_textureSize(uSamplerCubeArray, uint(0), _68_dummy_parameter));
uint _76_dummy_parameter;
int g = int(SPIRV_Cross_textureSize(uSamplerBuffer, 0u, _76_dummy_parameter));
uint _84_dummy_parameter;
int2 h = int2(SPIRV_Cross_textureSize(uSamplerMS, 0u, _84_dummy_parameter));
uint _92_dummy_parameter;
int3 i = int3(SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _92_dummy_parameter));
int _100;
SPIRV_Cross_textureSize(uSampler2D, 0u, _100);
int l1 = int(_100);
int _104;
SPIRV_Cross_textureSize(uSampler2DArray, 0u, _104);
int l2 = int(_104);
int _108;
SPIRV_Cross_textureSize(uSampler3D, 0u, _108);
int l3 = int(_108);
int _112;
SPIRV_Cross_textureSize(uSamplerCube, 0u, _112);
int l4 = int(_112);
int _116;
SPIRV_Cross_textureSize(uSamplerMS, 0u, _116);
int s0 = int(_116);
int _120;
SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _120);
int s1 = int(_120);
}
void main()
{
frag_main();
}

View File

@ -0,0 +1,131 @@
Texture1D<float4> uSampler1D : register(t0);
SamplerState _uSampler1D_sampler : register(s0);
Texture2D<float4> uSampler2D : register(t1);
SamplerState _uSampler2D_sampler : register(s1);
Texture2DArray<float4> uSampler2DArray : register(t2);
SamplerState _uSampler2DArray_sampler : register(s2);
Texture3D<float4> uSampler3D : register(t3);
SamplerState _uSampler3D_sampler : register(s3);
TextureCube<float4> uSamplerCube : register(t4);
SamplerState _uSamplerCube_sampler : register(s4);
TextureCubeArray<float4> uSamplerCubeArray : register(t5);
SamplerState _uSamplerCubeArray_sampler : register(s5);
Buffer<float4> uSamplerBuffer : register(t6);
Texture2DMS<float4> uSamplerMS : register(t7);
SamplerState _uSamplerMS_sampler : register(s7);
Texture2DMSArray<float4> uSamplerMSArray : register(t8);
SamplerState _uSamplerMSArray_sampler : register(s8);
uint SPIRV_Cross_textureSize(Texture1D<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(Level, ret.x, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2D<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture3D<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint SPIRV_Cross_textureSize(Buffer<float4> Tex, uint Level, out uint Param)
{
uint ret;
Tex.GetDimensions(ret.x);
return ret;
}
uint2 SPIRV_Cross_textureSize(TextureCube<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(Level, ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(TextureCubeArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);
return ret;
}
uint2 SPIRV_Cross_textureSize(Texture2DMS<float4> Tex, uint Level, out uint Param)
{
uint2 ret;
Tex.GetDimensions(ret.x, ret.y, Param);
return ret;
}
uint3 SPIRV_Cross_textureSize(Texture2DMSArray<float4> Tex, uint Level, out uint Param)
{
uint3 ret;
Tex.GetDimensions(ret.x, ret.y, ret.z, Param);
return ret;
}
void frag_main()
{
uint _17_dummy_parameter;
int a = int(SPIRV_Cross_textureSize(uSampler1D, uint(0), _17_dummy_parameter));
uint _27_dummy_parameter;
int2 b = int2(SPIRV_Cross_textureSize(uSampler2D, uint(0), _27_dummy_parameter));
uint _37_dummy_parameter;
int3 c = int3(SPIRV_Cross_textureSize(uSampler2DArray, uint(0), _37_dummy_parameter));
uint _45_dummy_parameter;
int3 d = int3(SPIRV_Cross_textureSize(uSampler3D, uint(0), _45_dummy_parameter));
uint _53_dummy_parameter;
int2 e = int2(SPIRV_Cross_textureSize(uSamplerCube, uint(0), _53_dummy_parameter));
uint _61_dummy_parameter;
int3 f = int3(SPIRV_Cross_textureSize(uSamplerCubeArray, uint(0), _61_dummy_parameter));
uint _69_dummy_parameter;
int g = int(SPIRV_Cross_textureSize(uSamplerBuffer, 0u, _69_dummy_parameter));
uint _77_dummy_parameter;
int2 h = int2(SPIRV_Cross_textureSize(uSamplerMS, 0u, _77_dummy_parameter));
uint _85_dummy_parameter;
int3 i = int3(SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _85_dummy_parameter));
int _89;
SPIRV_Cross_textureSize(uSampler1D, 0u, _89);
int l0 = int(_89);
int _93;
SPIRV_Cross_textureSize(uSampler2D, 0u, _93);
int l1 = int(_93);
int _97;
SPIRV_Cross_textureSize(uSampler2DArray, 0u, _97);
int l2 = int(_97);
int _101;
SPIRV_Cross_textureSize(uSampler3D, 0u, _101);
int l3 = int(_101);
int _105;
SPIRV_Cross_textureSize(uSamplerCube, 0u, _105);
int l4 = int(_105);
int _109;
SPIRV_Cross_textureSize(uSamplerCubeArray, 0u, _109);
int l5 = int(_109);
int _113;
SPIRV_Cross_textureSize(uSamplerMS, 0u, _113);
int s0 = int(_113);
int _117;
SPIRV_Cross_textureSize(uSamplerMSArray, 0u, _117);
int s1 = int(_117);
}
void main()
{
frag_main();
}

View File

@ -0,0 +1,53 @@
#version 450
layout(binding = 0) uniform sampler1D uSampler1D;
layout(binding = 1) uniform sampler2D uSampler2D;
layout(binding = 2) uniform sampler2DArray uSampler2DArray;
layout(binding = 3) uniform sampler3D uSampler3D;
layout(binding = 4) uniform samplerCube uSamplerCube;
layout(binding = 5) uniform samplerCubeArray uSamplerCubeArray;
layout(binding = 6) uniform samplerBuffer uSamplerBuffer;
layout(binding = 7) uniform sampler2DMS uSamplerMS;
layout(binding = 8) uniform sampler2DMSArray uSamplerMSArray;
layout(binding = 9, r32f) uniform readonly writeonly image1D uImage1D;
layout(binding = 10, r32f) uniform readonly writeonly image2D uImage2D;
layout(binding = 11, r32f) uniform readonly writeonly image2DArray uImage2DArray;
layout(binding = 12, r32f) uniform readonly writeonly image3D uImage3D;
layout(binding = 13, r32f) uniform readonly writeonly imageCube uImageCube;
layout(binding = 14, r32f) uniform readonly writeonly imageCubeArray uImageCubeArray;
layout(binding = 15, r32f) uniform readonly writeonly imageBuffer uImageBuffer;
layout(binding = 16, r32f) uniform readonly writeonly image2DMS uImageMS;
layout(binding = 17, r32f) uniform readonly writeonly image2DMSArray uImageMSArray;
void main()
{
int a = textureSize(uSampler1D, 0);
ivec2 b = textureSize(uSampler2D, 0);
ivec3 c = textureSize(uSampler2DArray, 0);
ivec3 d = textureSize(uSampler3D, 0);
ivec2 e = textureSize(uSamplerCube, 0);
ivec3 f = textureSize(uSamplerCubeArray, 0);
int g = textureSize(uSamplerBuffer);
ivec2 h = textureSize(uSamplerMS);
ivec3 i = textureSize(uSamplerMSArray);
int l0 = textureQueryLevels(uSampler1D);
int l1 = textureQueryLevels(uSampler2D);
int l2 = textureQueryLevels(uSampler2DArray);
int l3 = textureQueryLevels(uSampler3D);
int l4 = textureQueryLevels(uSamplerCube);
int l5 = textureQueryLevels(uSamplerCubeArray);
a = imageSize(uImage1D);
b = imageSize(uImage2D);
c = imageSize(uImage2DArray);
d = imageSize(uImage3D);
e = imageSize(uImageCube);
f = imageSize(uImageCubeArray);
g = imageSize(uImageBuffer);
h = imageSize(uImageMS);
i = imageSize(uImageMSArray);
int s0 = textureSamples(uSamplerMS);
int s1 = textureSamples(uSamplerMSArray);
int s2 = imageSamples(uImageMS);
int s3 = imageSamples(uImageMSArray);
}

View File

@ -0,0 +1,35 @@
#version 450
layout(binding = 0) uniform usampler1D uSampler1DUint;
layout(binding = 0) uniform isampler1D uSampler1DInt;
layout(binding = 0) uniform sampler1D uSampler1DFloat;
layout(binding = 1) uniform sampler2D uSampler2D;
layout(binding = 2) uniform isampler2DArray uSampler2DArray;
layout(binding = 3) uniform sampler3D uSampler3D;
layout(binding = 4) uniform samplerCube uSamplerCube;
layout(binding = 5) uniform usamplerCubeArray uSamplerCubeArray;
layout(binding = 6) uniform samplerBuffer uSamplerBuffer;
layout(binding = 7) uniform isampler2DMS uSamplerMS;
layout(binding = 8) uniform sampler2DMSArray uSamplerMSArray;
void main()
{
int a = textureSize(uSampler1DUint, 0);
a = textureSize(uSampler1DInt, 0);
a = textureSize(uSampler1DFloat, 0);
ivec3 c = textureSize(uSampler2DArray, 0);
ivec3 d = textureSize(uSampler3D, 0);
ivec2 e = textureSize(uSamplerCube, 0);
ivec3 f = textureSize(uSamplerCubeArray, 0);
int g = textureSize(uSamplerBuffer);
ivec2 h = textureSize(uSamplerMS);
ivec3 i = textureSize(uSamplerMSArray);
int l1 = textureQueryLevels(uSampler2D);
int l2 = textureQueryLevels(uSampler2DArray);
int l3 = textureQueryLevels(uSampler3D);
int l4 = textureQueryLevels(uSamplerCube);
int s0 = textureSamples(uSamplerMS);
int s1 = textureSamples(uSamplerMSArray);
}

View File

@ -0,0 +1,33 @@
#version 450
layout(binding = 0) uniform sampler1D uSampler1D;
layout(binding = 1) uniform sampler2D uSampler2D;
layout(binding = 2) uniform sampler2DArray uSampler2DArray;
layout(binding = 3) uniform sampler3D uSampler3D;
layout(binding = 4) uniform samplerCube uSamplerCube;
layout(binding = 5) uniform samplerCubeArray uSamplerCubeArray;
layout(binding = 6) uniform samplerBuffer uSamplerBuffer;
layout(binding = 7) uniform sampler2DMS uSamplerMS;
layout(binding = 8) uniform sampler2DMSArray uSamplerMSArray;
void main()
{
int a = textureSize(uSampler1D, 0);
ivec2 b = textureSize(uSampler2D, 0);
ivec3 c = textureSize(uSampler2DArray, 0);
ivec3 d = textureSize(uSampler3D, 0);
ivec2 e = textureSize(uSamplerCube, 0);
ivec3 f = textureSize(uSamplerCubeArray, 0);
int g = textureSize(uSamplerBuffer);
ivec2 h = textureSize(uSamplerMS);
ivec3 i = textureSize(uSamplerMSArray);
int l0 = textureQueryLevels(uSampler1D);
int l1 = textureQueryLevels(uSampler2D);
int l2 = textureQueryLevels(uSampler2DArray);
int l3 = textureQueryLevels(uSampler3D);
int l4 = textureQueryLevels(uSamplerCube);
int l5 = textureQueryLevels(uSamplerCubeArray);
int s0 = textureSamples(uSamplerMS);
int s1 = textureSamples(uSamplerMSArray);
}

View File

@ -0,0 +1,56 @@
#version 450
layout(binding = 0) uniform sampler1D uSampler1D;
layout(binding = 1) uniform sampler2D uSampler2D;
layout(binding = 2) uniform sampler2DArray uSampler2DArray;
layout(binding = 3) uniform sampler3D uSampler3D;
layout(binding = 4) uniform samplerCube uSamplerCube;
layout(binding = 5) uniform samplerCubeArray uSamplerCubeArray;
layout(binding = 6) uniform samplerBuffer uSamplerBuffer;
layout(binding = 7) uniform sampler2DMS uSamplerMS;
layout(binding = 8) uniform sampler2DMSArray uSamplerMSArray;
layout(r32f, binding = 9) uniform image1D uImage1D;
layout(r32f, binding = 10) uniform image2D uImage2D;
layout(r32f, binding = 11) uniform image2DArray uImage2DArray;
layout(r32f, binding = 12) uniform image3D uImage3D;
layout(r32f, binding = 13) uniform imageCube uImageCube;
layout(r32f, binding = 14) uniform imageCubeArray uImageCubeArray;
layout(r32f, binding = 15) uniform imageBuffer uImageBuffer;
layout(r32f, binding = 16) uniform image2DMS uImageMS;
layout(r32f, binding = 17) uniform image2DMSArray uImageMSArray;
void main()
{
int a = textureSize(uSampler1D, 0);
ivec2 b = textureSize(uSampler2D, 0);
ivec3 c = textureSize(uSampler2DArray, 0);
ivec3 d = textureSize(uSampler3D, 0);
ivec2 e = textureSize(uSamplerCube, 0);
ivec3 f = textureSize(uSamplerCubeArray, 0);
int g = textureSize(uSamplerBuffer);
ivec2 h = textureSize(uSamplerMS);
ivec3 i = textureSize(uSamplerMSArray);
int l0 = textureQueryLevels(uSampler1D);
int l1 = textureQueryLevels(uSampler2D);
int l2 = textureQueryLevels(uSampler2DArray);
int l3 = textureQueryLevels(uSampler3D);
int l4 = textureQueryLevels(uSamplerCube);
int l5 = textureQueryLevels(uSamplerCubeArray);
a = imageSize(uImage1D);
b = imageSize(uImage2D);
c = imageSize(uImage2DArray);
d = imageSize(uImage3D);
e = imageSize(uImageCube);
f = imageSize(uImageCubeArray);
g = imageSize(uImageBuffer);
h = imageSize(uImageMS);
i = imageSize(uImageMSArray);
int s0 = textureSamples(uSamplerMS);
int s1 = textureSamples(uSamplerMSArray);
int s2 = imageSamples(uImageMS);
int s3 = imageSamples(uImageMSArray);
}

View File

@ -3563,6 +3563,31 @@ string CompilerGLSL::bitcast_glsl(const SPIRType &result_type, uint32_t argument
return join(op, "(", to_expression(argument), ")");
}
std::string CompilerGLSL::bitcast_expression(SPIRType::BaseType target_type, uint32_t arg)
{
auto expr = to_expression(arg);
auto &src_type = expression_type(arg);
if (src_type.basetype != target_type)
{
auto target = src_type;
target.basetype = target_type;
expr = join(bitcast_glsl_op(target, src_type), "(", expr, ")");
}
return expr;
}
std::string CompilerGLSL::bitcast_expression(const SPIRType &target_type, SPIRType::BaseType expr_type,
const std::string &expr)
{
if (target_type.basetype == expr_type)
return expr;
auto src_type = target_type;
src_type.basetype = expr_type;
return join(bitcast_glsl_op(target_type, src_type), "(", expr, ")");
}
string CompilerGLSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
{
switch (builtin)
@ -5641,27 +5666,36 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
case OpImageQueryLevels:
{
uint32_t result_type = ops[0];
uint32_t id = ops[1];
if (!options.es && options.version < 430)
require_extension("GL_ARB_texture_query_levels");
if (options.es)
SPIRV_CROSS_THROW("textureQueryLevels not supported in ES profile.");
UFOP(textureQueryLevels);
auto expr = join("textureQueryLevels(", to_expression(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
break;
}
case OpImageQuerySamples:
{
auto *var = maybe_get_backing_variable(ops[2]);
if (!var)
SPIRV_CROSS_THROW(
"Bug. OpImageQuerySamples must have a backing variable so we know if the image is sampled or not.");
auto &type = expression_type(ops[2]);
uint32_t result_type = ops[0];
uint32_t id = ops[1];
auto &type = get<SPIRType>(var->basetype);
bool image = type.image.sampled == 2;
if (image)
UFOP(imageSamples);
string expr;
if (type.image.sampled == 2)
expr = join("imageSamples(", to_expression(ops[2]), ")");
else
UFOP(textureSamples);
expr = join("textureSamples(", to_expression(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
break;
}
@ -5674,8 +5708,16 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
}
case OpImageQuerySizeLod:
BFOP(textureSize);
{
uint32_t result_type = ops[0];
uint32_t id = ops[1];
auto expr = join("textureSize(", to_expression(ops[2]), ", ", bitcast_expression(SPIRType::Int, ops[3]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
break;
}
// Image load/store
case OpImageRead:
@ -5854,8 +5896,21 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (type.basetype == SPIRType::Image)
{
// The size of an image is always constant.
emit_op(result_type, id, join("imageSize(", to_expression(ops[2]), ")"), true);
string expr;
if (type.image.sampled == 2)
{
// The size of an image is always constant.
expr = join("imageSize(", to_expression(ops[2]), ")");
}
else
{
// This path is hit for samplerBuffers and multisampled images which do not have LOD.
expr = join("textureSize(", to_expression(ops[2]), ")");
}
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
}
else
SPIRV_CROSS_THROW("Invalid type for OpImageQuerySize.");

View File

@ -406,6 +406,10 @@ protected:
std::string bitcast_glsl(const SPIRType &result_type, uint32_t arg);
virtual std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type);
std::string bitcast_expression(SPIRType::BaseType target_type, uint32_t arg);
std::string bitcast_expression(const SPIRType &target_type, SPIRType::BaseType expr_type, const std::string &expr);
std::string build_composite_combiner(const uint32_t *elems, uint32_t length);
bool remove_duplicate_swizzle(std::string &op);
bool remove_unity_swizzle(uint32_t base, std::string &op);

View File

@ -83,7 +83,8 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
SPIRV_CROSS_THROW("Invalid dimension.");
}
const char *arrayed = type.image.arrayed ? "Array" : "";
return join("Texture", dim, arrayed, "<", type_to_glsl(imagetype), components, ">");
const char *ms = type.image.ms ? "MS" : "";
return join("Texture", dim, ms, arrayed, "<", type_to_glsl(imagetype), components, ">");
}
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
@ -938,6 +939,66 @@ void CompilerHLSL::emit_resources()
statement("");
}
}
if (required_textureSizeVariants != 0)
{
static const char *types[QueryTypeCount] = { "float4", "int4", "uint4" };
static const char *dims[QueryDimCount] = { "Texture1D", "Texture1DArray", "Texture2D", "Texture2DArray",
"Texture3D", "Buffer", "TextureCube", "TextureCubeArray",
"Texture2DMS", "Texture2DMSArray" };
static const bool has_lod[QueryDimCount] = { true, true, true, true, true, false, true, true, false, false };
static const char *ret_types[QueryDimCount] = {
"uint", "uint2", "uint2", "uint3", "uint3", "uint", "uint2", "uint3", "uint2", "uint3",
};
static const uint32_t return_arguments[QueryDimCount] = {
1, 2, 2, 3, 3, 1, 2, 3, 2, 3,
};
for (uint32_t index = 0; index < QueryDimCount; index++)
{
for (uint32_t type_index = 0; type_index < QueryTypeCount; type_index++)
{
uint32_t bit = 16 * type_index + index;
uint64_t mask = 1ull << bit;
if ((required_textureSizeVariants & mask) == 0)
continue;
statement(ret_types[index], " SPIRV_Cross_textureSize(", dims[index], "<", types[type_index],
"> Tex, uint Level, out uint Param)");
begin_scope();
statement(ret_types[index], " ret;");
switch (return_arguments[index])
{
case 1:
if (has_lod[index])
statement("Tex.GetDimensions(Level, ret.x, Param);");
else
statement("Tex.GetDimensions(ret.x);");
break;
case 2:
if (has_lod[index])
statement("Tex.GetDimensions(Level, ret.x, ret.y, Param);");
else
statement("Tex.GetDimensions(ret.x, ret.y, Param);");
break;
case 3:
if (has_lod[index])
statement("Tex.GetDimensions(Level, ret.x, ret.y, ret.z, Param);");
else
statement("Tex.GetDimensions(ret.x, ret.y, ret.z, Param);");
break;
}
statement("return ret;");
end_scope();
statement("");
}
}
}
}
string CompilerHLSL::layout_for_member(const SPIRType &, uint32_t)
@ -2337,12 +2398,127 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
break;
}
case OpImageQuerySizeLod:
{
auto result_type = ops[0];
auto id = ops[1];
require_texture_query_variant(expression_type(ops[2]));
auto dummy_samples_levels = join(get_fallback_name(id), "_dummy_parameter");
statement("uint ", dummy_samples_levels, ";");
auto expr = join("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", ",
bitcast_expression(SPIRType::UInt, ops[3]), ", ", dummy_samples_levels, ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::UInt, expr);
emit_op(result_type, id, expr, true);
break;
}
case OpImageQuerySize:
{
auto result_type = ops[0];
auto id = ops[1];
require_texture_query_variant(expression_type(ops[2]));
auto dummy_samples_levels = join(get_fallback_name(id), "_dummy_parameter");
statement("uint ", dummy_samples_levels, ";");
auto expr = join("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", 0u, ", dummy_samples_levels, ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::UInt, expr);
emit_op(result_type, id, expr, true);
break;
}
case OpImageQuerySamples:
case OpImageQueryLevels:
{
auto result_type = ops[0];
auto id = ops[1];
require_texture_query_variant(expression_type(ops[2]));
// Keep it simple and do not emit special variants to make this look nicer ...
// This stuff is barely, if ever, used.
forced_temporaries.insert(id);
auto &type = get<SPIRType>(result_type);
statement(variable_decl(type, to_name(id)), ";");
statement("SPIRV_Cross_textureSize(", to_expression(ops[2]), ", 0u, ", to_name(id), ");");
auto &restype = get<SPIRType>(ops[0]);
auto expr = bitcast_expression(restype, SPIRType::UInt, to_name(id));
set<SPIRExpression>(id, expr, result_type, true);
break;
}
default:
CompilerGLSL::emit_instruction(instruction);
break;
}
}
void CompilerHLSL::require_texture_query_variant(const SPIRType &type)
{
uint32_t bit = 0;
switch (type.image.dim)
{
case Dim1D:
bit = type.image.arrayed ? Query1DArray : Query1D;
break;
case Dim2D:
if (type.image.ms)
bit = type.image.arrayed ? Query2DMSArray : Query2DMS;
else
bit = type.image.arrayed ? Query2DArray : Query2D;
break;
case Dim3D:
bit = Query3D;
break;
case DimCube:
bit = type.image.arrayed ? QueryCubeArray : QueryCube;
break;
case DimBuffer:
bit = QueryBuffer;
break;
default:
SPIRV_CROSS_THROW("Unsupported query type.");
}
switch (get<SPIRType>(type.image.type).basetype)
{
case SPIRType::Float:
bit += QueryTypeFloat;
break;
case SPIRType::Int:
bit += QueryTypeInt;
break;
case SPIRType::UInt:
bit += QueryTypeUInt;
break;
default:
SPIRV_CROSS_THROW("Unsupported query type.");
}
uint64_t mask = 1ull << bit;
if ((required_textureSizeVariants & mask) == 0)
{
force_recompile = true;
required_textureSizeVariants |= mask;
}
}
string CompilerHLSL::compile()
{
// Do not deal with ES-isms like precision, older extensions and such.

View File

@ -98,6 +98,31 @@ private:
Options options;
bool requires_op_fmod = false;
bool requires_textureProj = false;
uint64_t required_textureSizeVariants = 0;
void require_texture_query_variant(const SPIRType &type);
enum TextureQueryVariantDim
{
Query1D = 0,
Query1DArray,
Query2D,
Query2DArray,
Query3D,
QueryBuffer,
QueryCube,
QueryCubeArray,
Query2DMS,
Query2DMSArray,
QueryDimCount
};
enum TextureQueryVariantType
{
QueryTypeFloat = 0,
QueryTypeInt = 16,
QueryTypeUInt = 32,
QueryTypeCount = 3
};
void emit_builtin_variables();
bool require_output = false;