GLSL: Implement sparse feedback.

This commit is contained in:
Hans-Kristian Arntzen 2020-06-04 15:50:28 +02:00
parent d385bf096f
commit 275974e062
8 changed files with 320 additions and 47 deletions

View File

@ -0,0 +1,105 @@
#version 450
#extension GL_ARB_sparse_texture2 : require
#extension GL_ARB_sparse_texture_clamp : require
struct ResType
{
int _m0;
vec4 _m1;
};
layout(binding = 0) uniform sampler2D uSamp;
layout(binding = 1) uniform sampler2DMS uSampMS;
layout(binding = 2, rgba8) uniform readonly image2D uImage;
layout(binding = 3, rgba8) uniform readonly image2DMS uImageMS;
layout(location = 0) in vec2 vUV;
void main()
{
int _144;
vec4 _145;
_144 = sparseTextureARB(uSamp, vUV, _145);
ResType _24 = ResType(_144, _145);
vec4 texel = _24._m1;
bool ret = sparseTexelsResidentARB(_24._m0);
int _146;
vec4 _147;
_146 = sparseTextureARB(uSamp, vUV, _147, 1.10000002384185791015625);
ResType _31 = ResType(_146, _147);
texel = _31._m1;
ret = sparseTexelsResidentARB(_31._m0);
int _148;
vec4 _149;
_148 = sparseTextureLodARB(uSamp, vUV, 1.0, _149);
ResType _38 = ResType(_148, _149);
texel = _38._m1;
ret = sparseTexelsResidentARB(_38._m0);
int _150;
vec4 _151;
_150 = sparseTextureOffsetARB(uSamp, vUV, ivec2(1), _151);
ResType _47 = ResType(_150, _151);
texel = _47._m1;
ret = sparseTexelsResidentARB(_47._m0);
int _152;
vec4 _153;
_152 = sparseTextureOffsetARB(uSamp, vUV, ivec2(2), _153, 0.5);
ResType _56 = ResType(_152, _153);
texel = _56._m1;
ret = sparseTexelsResidentARB(_56._m0);
int _154;
vec4 _155;
_154 = sparseTexelFetchARB(uSamp, ivec2(vUV), 1, _155);
ResType _64 = ResType(_154, _155);
texel = _64._m1;
ret = sparseTexelsResidentARB(_64._m0);
int _156;
vec4 _157;
_156 = sparseTexelFetchARB(uSampMS, ivec2(vUV), 2, _157);
ResType _76 = ResType(_156, _157);
texel = _76._m1;
ret = sparseTexelsResidentARB(_76._m0);
int _158;
vec4 _159;
_158 = sparseTexelFetchOffsetARB(uSamp, ivec2(vUV), 1, ivec2(2, 3), _159);
ResType _86 = ResType(_158, _159);
texel = _86._m1;
ret = sparseTexelsResidentARB(_86._m0);
int _160;
vec4 _161;
_160 = sparseTextureLodOffsetARB(uSamp, vUV, 1.5, ivec2(2, 3), _161);
ResType _93 = ResType(_160, _161);
texel = _93._m1;
ret = sparseTexelsResidentARB(_93._m0);
int _162;
vec4 _163;
_162 = sparseTextureGradARB(uSamp, vUV, vec2(1.0), vec2(3.0), _163);
ResType _102 = ResType(_162, _163);
texel = _102._m1;
ret = sparseTexelsResidentARB(_102._m0);
int _164;
vec4 _165;
_164 = sparseTextureGradOffsetARB(uSamp, vUV, vec2(1.0), vec2(3.0), ivec2(-2, -3), _165);
ResType _111 = ResType(_164, _165);
texel = _111._m1;
ret = sparseTexelsResidentARB(_111._m0);
int _166;
vec4 _167;
_166 = sparseTextureClampARB(uSamp, vUV, 4.0, _167);
ResType _118 = ResType(_166, _167);
texel = _118._m1;
ret = sparseTexelsResidentARB(_118._m0);
int _168;
vec4 _169;
_168 = sparseImageLoadARB(uImage, ivec2(vUV), _169);
ResType _128 = ResType(_168, _169);
texel = _128._m1;
ret = sparseTexelsResidentARB(_128._m0);
int _170;
vec4 _171;
_170 = sparseImageLoadARB(uImageMS, ivec2(vUV), 1, _171);
ResType _138 = ResType(_170, _171);
texel = _138._m1;
ret = sparseTexelsResidentARB(_138._m0);
}

View File

@ -0,0 +1,31 @@
#version 450
#extension GL_ARB_sparse_texture2 : require
#extension GL_ARB_sparse_texture_clamp : require
layout(set = 0, binding = 0) uniform sampler2D uSamp;
layout(set = 0, binding = 1) uniform sampler2DMS uSampMS;
layout(set = 0, binding = 2, rgba8) uniform image2D uImage;
layout(set = 0, binding = 3, rgba8) uniform image2DMS uImageMS;
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 vUV;
void main()
{
vec4 texel;
bool ret;
ret = sparseTexelsResidentARB(sparseTextureARB(uSamp, vUV, texel));
ret = sparseTexelsResidentARB(sparseTextureARB(uSamp, vUV, texel, 1.1));
ret = sparseTexelsResidentARB(sparseTextureLodARB(uSamp, vUV, 1.0, texel));
ret = sparseTexelsResidentARB(sparseTextureOffsetARB(uSamp, vUV, ivec2(1, 1), texel));
ret = sparseTexelsResidentARB(sparseTextureOffsetARB(uSamp, vUV, ivec2(2, 2), texel, 0.5));
ret = sparseTexelsResidentARB(sparseTexelFetchARB(uSamp, ivec2(vUV), 1, texel));
ret = sparseTexelsResidentARB(sparseTexelFetchARB(uSampMS, ivec2(vUV), 2, texel));
ret = sparseTexelsResidentARB(sparseTexelFetchOffsetARB(uSamp, ivec2(vUV), 1, ivec2(2, 3), texel));
ret = sparseTexelsResidentARB(sparseTextureLodOffsetARB(uSamp, vUV, 1.5, ivec2(2, 3), texel));
ret = sparseTexelsResidentARB(sparseTextureGradARB(uSamp, vUV, vec2(1.0), vec2(3.0), texel));
ret = sparseTexelsResidentARB(sparseTextureGradOffsetARB(uSamp, vUV, vec2(1.0), vec2(3.0), ivec2(-2, -3), texel));
ret = sparseTexelsResidentARB(sparseTextureClampARB(uSamp, vUV, 4.0, texel));
ret = sparseTexelsResidentARB(sparseImageLoadARB(uImage, ivec2(vUV), texel));
ret = sparseTexelsResidentARB(sparseImageLoadARB(uImageMS, ivec2(vUV), 1, texel));
}

View File

@ -5363,7 +5363,29 @@ static inline bool image_opcode_is_sample_no_dref(Op op)
} }
} }
void CompilerGLSL::emit_texture_op(const Instruction &i) void CompilerGLSL::emit_sparse_feedback_temporaries(uint32_t result_type_id, uint32_t id,
uint32_t &feedback_id, uint32_t &texel_id)
{
// Need to allocate two temporaries.
if (options.es)
SPIRV_CROSS_THROW("Sparse texture feedback is not supported on ESSL.");
require_extension_internal("GL_ARB_sparse_texture2");
auto &temps = extra_sub_expressions[id];
if (temps == 0)
temps = ir.increase_bound_by(2);
feedback_id = temps + 0;
texel_id = temps + 1;
auto &return_type = get<SPIRType>(result_type_id);
if (return_type.basetype != SPIRType::Struct || return_type.member_types.size() != 2)
SPIRV_CROSS_THROW("Invalid return type for sparse feedback.");
emit_uninitialized_temporary(return_type.member_types[0], feedback_id);
emit_uninitialized_temporary(return_type.member_types[1], texel_id);
}
void CompilerGLSL::emit_texture_op(const Instruction &i, bool sparse)
{ {
auto *ops = stream(i); auto *ops = stream(i);
auto op = static_cast<Op>(i.op); auto op = static_cast<Op>(i.op);
@ -5372,13 +5394,29 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
uint32_t result_type_id = ops[0]; uint32_t result_type_id = ops[0];
uint32_t id = ops[1]; uint32_t id = ops[1];
auto &return_type = get<SPIRType>(result_type_id);
uint32_t sparse_code_id = 0;
uint32_t sparse_texel_id = 0;
if (sparse)
emit_sparse_feedback_temporaries(result_type_id, id, sparse_code_id, sparse_texel_id);
bool forward = false; bool forward = false;
string expr = to_texture_op(i, &forward, inherited_expressions); string expr = to_texture_op(i, sparse, &forward, inherited_expressions);
if (sparse)
{
statement(to_expression(sparse_code_id), " = ", expr, ";");
expr = join(type_to_glsl(return_type), "(", to_expression(sparse_code_id), ", ", to_expression(sparse_texel_id), ")");
forward = true;
inherited_expressions.clear();
}
emit_op(result_type_id, id, expr, forward); emit_op(result_type_id, id, expr, forward);
for (auto &inherit : inherited_expressions) for (auto &inherit : inherited_expressions)
inherit_expression_dependencies(id, inherit); inherit_expression_dependencies(id, inherit);
// Do not register sparse ops as control dependent as they are always lowered to a temporary.
switch (op) switch (op)
{ {
case OpImageSampleDrefImplicitLod: case OpImageSampleDrefImplicitLod:
@ -5393,7 +5431,7 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
} }
} }
std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward, std::string CompilerGLSL::to_texture_op(const Instruction &i, bool sparse, bool *forward,
SmallVector<uint32_t> &inherited_expressions) SmallVector<uint32_t> &inherited_expressions)
{ {
auto *ops = stream(i); auto *ops = stream(i);
@ -5422,6 +5460,8 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
{ {
case OpImageSampleDrefImplicitLod: case OpImageSampleDrefImplicitLod:
case OpImageSampleDrefExplicitLod: case OpImageSampleDrefExplicitLod:
case OpImageSparseSampleDrefImplicitLod:
case OpImageSparseSampleDrefExplicitLod:
dref = ops[4]; dref = ops[4];
opt = &ops[5]; opt = &ops[5];
length -= 5; length -= 5;
@ -5429,6 +5469,8 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
case OpImageSampleProjDrefImplicitLod: case OpImageSampleProjDrefImplicitLod:
case OpImageSampleProjDrefExplicitLod: case OpImageSampleProjDrefExplicitLod:
case OpImageSparseSampleProjDrefImplicitLod:
case OpImageSparseSampleProjDrefExplicitLod:
dref = ops[4]; dref = ops[4];
opt = &ops[5]; opt = &ops[5];
length -= 5; length -= 5;
@ -5436,6 +5478,7 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
break; break;
case OpImageDrefGather: case OpImageDrefGather:
case OpImageSparseDrefGather:
dref = ops[4]; dref = ops[4];
opt = &ops[5]; opt = &ops[5];
length -= 5; length -= 5;
@ -5443,6 +5486,7 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
break; break;
case OpImageGather: case OpImageGather:
case OpImageSparseGather:
comp = ops[4]; comp = ops[4];
opt = &ops[5]; opt = &ops[5];
length -= 5; length -= 5;
@ -5450,6 +5494,7 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
break; break;
case OpImageFetch: case OpImageFetch:
case OpImageSparseFetch:
case OpImageRead: // Reads == fetches in Metal (other langs will not get here) case OpImageRead: // Reads == fetches in Metal (other langs will not get here)
opt = &ops[4]; opt = &ops[4];
length -= 4; length -= 4;
@ -5458,6 +5503,8 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
case OpImageSampleProjImplicitLod: case OpImageSampleProjImplicitLod:
case OpImageSampleProjExplicitLod: case OpImageSampleProjExplicitLod:
case OpImageSparseSampleProjImplicitLod:
case OpImageSparseSampleProjExplicitLod:
opt = &ops[4]; opt = &ops[4];
length -= 4; length -= 4;
proj = true; proj = true;
@ -5542,10 +5589,14 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
string expr; string expr;
expr += to_function_name(img, imgtype, !!fetch, !!gather, !!proj, !!coffsets, (!!coffset || !!offset), expr += to_function_name(img, imgtype, !!fetch, !!gather, !!proj, !!coffsets, (!!coffset || !!offset),
(!!grad_x || !!grad_y), !!dref, lod, minlod); (!!grad_x || !!grad_y), !!dref, sparse, lod, minlod);
expr += "("; expr += "(";
uint32_t sparse_texel_id = 0;
if (sparse)
sparse_texel_id = extra_sub_expressions[ops[1]] + 1;
expr += to_function_args(img, imgtype, fetch, gather, proj, coord, coord_components, dref, grad_x, grad_y, lod, expr += to_function_args(img, imgtype, fetch, gather, proj, coord, coord_components, dref, grad_x, grad_y, lod,
coffset, offset, bias, comp, sample, minlod, forward); coffset, offset, bias, comp, sample, sparse_texel_id, minlod, forward);
expr += ")"; expr += ")";
// texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here. // texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here.
@ -5576,7 +5627,7 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool *forward,
expr = remap_swizzle(result_type, 1, expr); expr = remap_swizzle(result_type, 1, expr);
} }
if (!backend.support_small_type_sampling_result && result_type.width < 32) if (!sparse && !backend.support_small_type_sampling_result && result_type.width < 32)
{ {
// Just value cast (narrowing) to expected type since we cannot rely on narrowing to work automatically. // Just value cast (narrowing) to expected type since we cannot rely on narrowing to work automatically.
// Hopefully compiler picks this up and converts the texturing instruction to the appropriate precision. // Hopefully compiler picks this up and converts the texturing instruction to the appropriate precision.
@ -5602,10 +5653,15 @@ bool CompilerGLSL::expression_is_constant_null(uint32_t id) const
// For some subclasses, the function is a method on the specified image. // For some subclasses, the function is a method on the specified image.
string CompilerGLSL::to_function_name(VariableID tex, const SPIRType &imgtype, bool is_fetch, bool is_gather, string CompilerGLSL::to_function_name(VariableID tex, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool, bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool,
uint32_t lod, uint32_t minlod) bool is_sparse_feedback, uint32_t lod, uint32_t minlod)
{ {
if (minlod != 0) if (minlod != 0)
SPIRV_CROSS_THROW("Sparse texturing not yet supported."); {
if (options.es)
SPIRV_CROSS_THROW("Sparse residency is not supported in ESSL.");
require_extension_internal("GL_ARB_sparse_texture_clamp");
return "sparseTextureClampARB";
}
string fname; string fname;
@ -5625,11 +5681,14 @@ string CompilerGLSL::to_function_name(VariableID tex, const SPIRType &imgtype, b
workaround_lod_array_shadow_as_grad = true; workaround_lod_array_shadow_as_grad = true;
} }
if (is_sparse_feedback)
fname += "sparse";
if (is_fetch) if (is_fetch)
fname += "texelFetch"; fname += is_sparse_feedback ? "TexelFetch" : "texelFetch";
else else
{ {
fname += "texture"; fname += is_sparse_feedback ? "Texture" : "texture";
if (is_gather) if (is_gather)
fname += "Gather"; fname += "Gather";
@ -5646,6 +5705,9 @@ string CompilerGLSL::to_function_name(VariableID tex, const SPIRType &imgtype, b
if (has_offset) if (has_offset)
fname += "Offset"; fname += "Offset";
if (is_sparse_feedback)
fname += "ARB";
return is_legacy() ? legacy_tex_op(fname, imgtype, lod, tex) : fname; return is_legacy() ? legacy_tex_op(fname, imgtype, lod, tex) : fname;
} }
@ -5694,7 +5756,7 @@ std::string CompilerGLSL::convert_separate_image_to_expression(uint32_t id)
string CompilerGLSL::to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, string CompilerGLSL::to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref,
uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset,
uint32_t bias, uint32_t comp, uint32_t sample, uint32_t /*minlod*/, uint32_t bias, uint32_t comp, uint32_t sample, uint32_t sparse_texel_id, uint32_t minlod,
bool *p_forward) bool *p_forward)
{ {
string farg_str; string farg_str;
@ -5869,6 +5931,25 @@ string CompilerGLSL::to_function_args(VariableID img, const SPIRType &imgtype, b
farg_str += to_expression(offset); farg_str += to_expression(offset);
} }
if (sample)
{
farg_str += ", ";
farg_str += to_expression(sample);
}
if (minlod)
{
farg_str += ", ";
farg_str += to_expression(minlod);
}
if (sparse_texel_id)
{
// Sparse texel output parameter comes after everything else, except it's before the optional, component/bias arguments.
farg_str += ", ";
farg_str += to_expression(sparse_texel_id);
}
if (bias) if (bias)
{ {
forward = forward && should_forward(bias); forward = forward && should_forward(bias);
@ -5883,12 +5964,6 @@ string CompilerGLSL::to_function_args(VariableID img, const SPIRType &imgtype, b
farg_str += to_expression(comp); farg_str += to_expression(comp);
} }
if (sample)
{
farg_str += ", ";
farg_str += to_expression(sample);
}
*p_forward = forward; *p_forward = forward;
return farg_str; return farg_str;
@ -10081,7 +10156,29 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
case OpImageGather: case OpImageGather:
case OpImageDrefGather: case OpImageDrefGather:
// Gets a bit hairy, so move this to a separate instruction. // Gets a bit hairy, so move this to a separate instruction.
emit_texture_op(instruction); emit_texture_op(instruction, false);
break;
case OpImageSparseSampleExplicitLod:
case OpImageSparseSampleProjExplicitLod:
case OpImageSparseSampleDrefExplicitLod:
case OpImageSparseSampleProjDrefExplicitLod:
case OpImageSparseSampleImplicitLod:
case OpImageSparseSampleProjImplicitLod:
case OpImageSparseSampleDrefImplicitLod:
case OpImageSparseSampleProjDrefImplicitLod:
case OpImageSparseFetch:
case OpImageSparseGather:
case OpImageSparseDrefGather:
// Gets a bit hairy, so move this to a separate instruction.
emit_texture_op(instruction, true);
break;
case OpImageSparseTexelsResident:
if (options.es)
SPIRV_CROSS_THROW("Sparse feedback is not supported in GLSL.");
require_extension_internal("GL_ARB_sparse_texture2");
GLSL_UFOP(sparseTexelsResidentARB);
break; break;
case OpImage: case OpImage:
@ -10174,6 +10271,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
// Image load/store // Image load/store
case OpImageRead: case OpImageRead:
case OpImageSparseRead:
{ {
// We added Nonreadable speculatively to the OpImage variable due to glslangValidator // We added Nonreadable speculatively to the OpImage variable due to glslangValidator
// not adding the proper qualifiers. // not adding the proper qualifiers.
@ -10267,6 +10365,12 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
} }
else else
{ {
bool sparse = opcode == OpImageSparseRead;
uint32_t sparse_code_id = 0;
uint32_t sparse_texel_id = 0;
if (sparse)
emit_sparse_feedback_temporaries(ops[0], ops[1], sparse_code_id, sparse_texel_id);
// imageLoad only accepts int coords, not uint. // imageLoad only accepts int coords, not uint.
auto coord_expr = to_expression(ops[3]); auto coord_expr = to_expression(ops[3]);
auto target_coord_type = expression_type(ops[3]); auto target_coord_type = expression_type(ops[3]);
@ -10274,20 +10378,46 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
coord_expr = bitcast_expression(target_coord_type, expression_type(ops[3]).basetype, coord_expr); coord_expr = bitcast_expression(target_coord_type, expression_type(ops[3]).basetype, coord_expr);
// Plain image load/store. // Plain image load/store.
if (type.image.ms) if (sparse)
{ {
uint32_t operands = ops[4]; if (type.image.ms)
if (operands != ImageOperandsSampleMask || length != 6) {
SPIRV_CROSS_THROW("Multisampled image used in OpImageRead, but unexpected operand mask was used."); uint32_t operands = ops[4];
if (operands != ImageOperandsSampleMask || length != 6)
SPIRV_CROSS_THROW(
"Multisampled image used in OpImageRead, but unexpected operand mask was used.");
uint32_t samples = ops[5]; uint32_t samples = ops[5];
imgexpr = statement(to_expression(sparse_code_id), " = sparseImageLoadARB(", to_expression(ops[2]), ", ",
join("imageLoad(", to_expression(ops[2]), ", ", coord_expr, ", ", to_expression(samples), ")"); coord_expr, ", ", to_expression(samples), ", ", to_expression(sparse_texel_id), ");");
}
else
{
statement(to_expression(sparse_code_id), " = sparseImageLoadARB(", to_expression(ops[2]), ", ",
coord_expr, ", ", to_expression(sparse_texel_id), ");");
}
imgexpr = join(type_to_glsl(get<SPIRType>(result_type)), "(",
to_expression(sparse_code_id), ", ", to_expression(sparse_texel_id), ")");
} }
else else
imgexpr = join("imageLoad(", to_expression(ops[2]), ", ", coord_expr, ")"); {
if (type.image.ms)
{
uint32_t operands = ops[4];
if (operands != ImageOperandsSampleMask || length != 6)
SPIRV_CROSS_THROW(
"Multisampled image used in OpImageRead, but unexpected operand mask was used.");
imgexpr = remap_swizzle(get<SPIRType>(result_type), 4, imgexpr); uint32_t samples = ops[5];
imgexpr =
join("imageLoad(", to_expression(ops[2]), ", ", coord_expr, ", ", to_expression(samples), ")");
}
else
imgexpr = join("imageLoad(", to_expression(ops[2]), ", ", coord_expr, ")");
}
if (!sparse)
imgexpr = remap_swizzle(get<SPIRType>(result_type), 4, imgexpr);
pure = false; pure = false;
} }

View File

@ -268,8 +268,8 @@ protected:
const SpecializationConstant &y, const SpecializationConstant &z); const SpecializationConstant &y, const SpecializationConstant &z);
virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id); virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
virtual void emit_texture_op(const Instruction &i); virtual void emit_texture_op(const Instruction &i, bool sparse);
virtual std::string to_texture_op(const Instruction &i, bool *forward, virtual std::string to_texture_op(const Instruction &i, bool sparse, bool *forward,
SmallVector<uint32_t> &inherited_expressions); SmallVector<uint32_t> &inherited_expressions);
virtual void emit_subgroup_op(const Instruction &i); virtual void emit_subgroup_op(const Instruction &i);
virtual std::string type_to_glsl(const SPIRType &type, uint32_t id = 0); virtual std::string type_to_glsl(const SPIRType &type, uint32_t id = 0);
@ -286,12 +286,13 @@ protected:
virtual std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id); virtual std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id);
virtual std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, virtual std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad,
bool has_dref, uint32_t lod, uint32_t minlod); bool has_dref, bool is_sparse_feedback, uint32_t lod, uint32_t minlod);
virtual std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, virtual std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref,
uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset,
uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample, uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample,
uint32_t minlod, bool *p_forward); uint32_t sparse_texel, uint32_t minlod, bool *p_forward);
void emit_sparse_feedback_temporaries(uint32_t result_type_id, uint32_t id, uint32_t &feedback_id, uint32_t &texel_id);
virtual void emit_buffer_block(const SPIRVariable &type); virtual void emit_buffer_block(const SPIRVariable &type);
virtual void emit_push_constant_block(const SPIRVariable &var); virtual void emit_push_constant_block(const SPIRVariable &var);
virtual void emit_uniform(const SPIRVariable &var); virtual void emit_uniform(const SPIRVariable &var);

View File

@ -2607,8 +2607,11 @@ void CompilerHLSL::emit_fixup()
} }
} }
void CompilerHLSL::emit_texture_op(const Instruction &i) void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse)
{ {
if (sparse)
SPIRV_CROSS_THROW("Sparse feedback not yet supported in HLSL.");
auto *ops = stream(i); auto *ops = stream(i);
auto op = static_cast<Op>(i.op); auto op = static_cast<Op>(i.op);
uint32_t length = i.length; uint32_t length = i.length;
@ -4886,7 +4889,7 @@ void CompilerHLSL::emit_instruction(const Instruction &instruction)
} }
case OpImageQueryLod: case OpImageQueryLod:
emit_texture_op(instruction); emit_texture_op(instruction, false);
break; break;
case OpImageQuerySizeLod: case OpImageQuerySizeLod:

View File

@ -204,7 +204,7 @@ private:
void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set<uint32_t> &active_locations); void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set<uint32_t> &active_locations);
void emit_builtin_inputs_in_struct(); void emit_builtin_inputs_in_struct();
void emit_builtin_outputs_in_struct(); void emit_builtin_outputs_in_struct();
void emit_texture_op(const Instruction &i) override; void emit_texture_op(const Instruction &i, bool sparse) override;
void emit_instruction(const Instruction &instruction) override; void emit_instruction(const Instruction &instruction) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
uint32_t count) override; uint32_t count) override;

View File

@ -6215,7 +6215,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
} }
} }
emit_texture_op(instruction); emit_texture_op(instruction, false);
break; break;
} }
@ -6303,7 +6303,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
statement(join(to_expression(img_id), ".write(", statement(join(to_expression(img_id), ".write(",
remap_swizzle(store_type, texel_type.vecsize, to_expression(texel_id)), ", ", remap_swizzle(store_type, texel_type.vecsize, to_expression(texel_id)), ", ",
to_function_args(img_id, img_type, true, false, false, coord_id, 0, 0, 0, 0, lod, 0, 0, 0, 0, 0, to_function_args(img_id, img_type, true, false, false, coord_id, 0, 0, 0, 0, lod, 0, 0, 0, 0, 0, 0,
0, &forward), 0, &forward),
");")); ");"));
@ -6746,8 +6746,11 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
previous_instruction_opcode = opcode; previous_instruction_opcode = opcode;
} }
void CompilerMSL::emit_texture_op(const Instruction &i) void CompilerMSL::emit_texture_op(const Instruction &i, bool sparse)
{ {
if (sparse)
SPIRV_CROSS_THROW("Sparse feedback not yet supported in MSL.");
if (msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses) if (msl_options.is_ios() && msl_options.ios_use_framebuffer_fetch_subpasses)
{ {
auto *ops = stream(i); auto *ops = stream(i);
@ -6771,7 +6774,7 @@ void CompilerMSL::emit_texture_op(const Instruction &i)
} }
// Fallback to default implementation // Fallback to default implementation
CompilerGLSL::emit_texture_op(i); CompilerGLSL::emit_texture_op(i, sparse);
} }
void CompilerMSL::emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem) void CompilerMSL::emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem)
@ -7486,7 +7489,7 @@ static bool needs_chroma_reconstruction(const MSLConstexprSampler *constexpr_sam
// Returns the texture sampling function string for the specified image and sampling characteristics. // Returns the texture sampling function string for the specified image and sampling characteristics.
string CompilerMSL::to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool, bool, string CompilerMSL::to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool, bool,
bool, bool, bool has_dref, uint32_t, uint32_t) bool, bool, bool has_dref, bool, uint32_t, uint32_t)
{ {
const MSLConstexprSampler *constexpr_sampler = nullptr; const MSLConstexprSampler *constexpr_sampler = nullptr;
bool is_dynamic_img_sampler = false; bool is_dynamic_img_sampler = false;
@ -7651,7 +7654,7 @@ static inline bool sampling_type_needs_f32_conversion(const SPIRType &type)
string CompilerMSL::to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, string CompilerMSL::to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, uint32_t coord, uint32_t, uint32_t dref, uint32_t grad_x, bool is_proj, uint32_t coord, uint32_t, uint32_t dref, uint32_t grad_x,
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) uint32_t comp, uint32_t sample, uint32_t /*sparse_texel_id*/, uint32_t minlod, bool *p_forward)
{ {
const MSLConstexprSampler *constexpr_sampler = nullptr; const MSLConstexprSampler *constexpr_sampler = nullptr;
bool is_dynamic_img_sampler = false; bool is_dynamic_img_sampler = false;
@ -8128,7 +8131,7 @@ void CompilerMSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_id
set<SPIRCombinedImageSampler>(result_id, result_type, image_id, samp_id); set<SPIRCombinedImageSampler>(result_id, result_type, image_id, samp_id);
} }
string CompilerMSL::to_texture_op(const Instruction &i, bool *forward, SmallVector<uint32_t> &inherited_expressions) string CompilerMSL::to_texture_op(const Instruction &i, bool sparse, bool *forward, SmallVector<uint32_t> &inherited_expressions)
{ {
auto *ops = stream(i); auto *ops = stream(i);
uint32_t result_type_id = ops[0]; uint32_t result_type_id = ops[0];
@ -8196,7 +8199,7 @@ string CompilerMSL::to_texture_op(const Instruction &i, bool *forward, SmallVect
expr += "spvTextureSwizzle("; expr += "spvTextureSwizzle(";
} }
string inner_expr = CompilerGLSL::to_texture_op(i, forward, inherited_expressions); string inner_expr = CompilerGLSL::to_texture_op(i, sparse, forward, inherited_expressions);
if (constexpr_sampler && constexpr_sampler->ycbcr_conversion_enable && !is_dynamic_img_sampler) if (constexpr_sampler && constexpr_sampler->ycbcr_conversion_enable && !is_dynamic_img_sampler)
{ {

View File

@ -583,7 +583,7 @@ protected:
// If the underlying resource has been used for comparison then duplicate loads of that resource must be too // If the underlying resource has been used for comparison then duplicate loads of that resource must be too
// Use Metal's native frame-buffer fetch API for subpass inputs. // Use Metal's native frame-buffer fetch API for subpass inputs.
void emit_texture_op(const Instruction &i) override; void emit_texture_op(const Instruction &i, bool sparse) override;
void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op); void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
void emit_instruction(const Instruction &instr) override; void emit_instruction(const Instruction &instr) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
@ -594,7 +594,7 @@ protected:
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override; void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
void emit_subgroup_op(const Instruction &i) override; void emit_subgroup_op(const Instruction &i) override;
std::string to_texture_op(const Instruction &i, bool *forward, std::string to_texture_op(const Instruction &i, bool sparse, bool *forward,
SmallVector<uint32_t> &inherited_expressions) override; SmallVector<uint32_t> &inherited_expressions) override;
void emit_fixup() override; void emit_fixup() override;
std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
@ -619,12 +619,12 @@ protected:
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override; std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
std::string to_name(uint32_t id, bool allow_alias = true) const override; std::string to_name(uint32_t id, bool allow_alias = true) const override;
std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
bool has_array_offsets, bool has_offset, bool has_grad, bool has_dref, uint32_t lod, bool has_array_offsets, bool has_offset, bool has_grad, bool has_dref, bool is_sparse_feedback,
uint32_t minlod) override; uint32_t lod, uint32_t minlod) override;
std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x, uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override; uint32_t comp, uint32_t sample, uint32_t sparse_texel_id, uint32_t minlod, bool *p_forward) override;
std::string to_initializer_expression(const SPIRVariable &var) override; std::string to_initializer_expression(const SPIRVariable &var) override;
std::string to_zero_initialized_expression(uint32_t type_id) override; std::string to_zero_initialized_expression(uint32_t type_id) override;