|
|
|
@ -260,6 +260,13 @@ bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) { |
|
|
|
return ctx.textures.at(info.descriptor_index).is_multisample; |
|
|
|
} |
|
|
|
|
|
|
|
bool IsTextureInteger(EmitContext& ctx, const IR::TextureInstInfo& info) { |
|
|
|
if (info.type == TextureType::Buffer) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
return ctx.textures.at(info.descriptor_index).is_integer; |
|
|
|
} |
|
|
|
|
|
|
|
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
if (info.relaxed_precision != 0) { |
|
|
|
@ -480,11 +487,14 @@ Id EmitBoundImageWrite(EmitContext&) { |
|
|
|
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
|
|
|
Id bias_lc, const IR::Value& offset) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
Id color; |
|
|
|
if (ctx.stage == Stage::Fragment) { |
|
|
|
const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, |
|
|
|
bias_lc, offset); |
|
|
|
return Emit(&EmitContext::OpImageSparseSampleImplicitLod, |
|
|
|
&EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], |
|
|
|
color = Emit(&EmitContext::OpImageSparseSampleImplicitLod, |
|
|
|
&EmitContext::OpImageSampleImplicitLod, ctx, inst, result_type, |
|
|
|
Texture(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); |
|
|
|
} else { |
|
|
|
// We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as
|
|
|
|
@ -492,26 +502,29 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& |
|
|
|
// derivatives
|
|
|
|
const Id lod{ctx.Const(0.0f)}; |
|
|
|
const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset); |
|
|
|
return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
|
|
|
color = Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, |
|
|
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
|
|
|
} |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
|
|
|
Id lod, const IR::Value& offset) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
const ImageOperands operands(ctx, false, true, false, lod, offset); |
|
|
|
|
|
|
|
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, |
|
|
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
|
|
|
#ifdef __ANDROID__
|
|
|
|
if (Settings::values.fix_bloom_effects.GetValue()) { |
|
|
|
if (!is_integer && Settings::values.fix_bloom_effects.GetValue()) { |
|
|
|
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f)); |
|
|
|
} |
|
|
|
#endif
|
|
|
|
return result; |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], result) : result; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, |
|
|
|
@ -547,30 +560,39 @@ Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va |
|
|
|
Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
|
|
|
const IR::Value& offset, const IR::Value& offset2) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
const ImageOperands operands(ctx, offset, offset2); |
|
|
|
if (ctx.profile.need_gather_subpixel_offset) { |
|
|
|
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords); |
|
|
|
} |
|
|
|
return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, |
|
|
|
ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component), |
|
|
|
operands.MaskOptional(), operands.Span()); |
|
|
|
const Id color{Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, |
|
|
|
result_type, Texture(ctx, info, index), coords, |
|
|
|
ctx.Const(info.gather_component), operands.MaskOptional(), |
|
|
|
operands.Span())}; |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
|
|
|
const IR::Value& offset, const IR::Value& offset2, Id dref) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
const ImageOperands operands(ctx, offset, offset2); |
|
|
|
if (ctx.profile.need_gather_subpixel_offset) { |
|
|
|
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords); |
|
|
|
} |
|
|
|
return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst, |
|
|
|
ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.MaskOptional(), |
|
|
|
operands.Span()); |
|
|
|
const Id color{Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, |
|
|
|
ctx, inst, result_type, Texture(ctx, info, index), coords, dref, |
|
|
|
operands.MaskOptional(), operands.Span())}; |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
|
|
|
Id lod, Id ms) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
AddOffsetToCoordinates(ctx, info, coords, offset); |
|
|
|
if (info.type == TextureType::Buffer) { |
|
|
|
lod = Id{}; |
|
|
|
@ -580,8 +602,10 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c |
|
|
|
lod = Id{}; |
|
|
|
} |
|
|
|
const ImageOperands operands(lod, ms); |
|
|
|
return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], |
|
|
|
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); |
|
|
|
const Id color{Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, |
|
|
|
result_type, TextureImage(ctx, info, index), coords, |
|
|
|
operands.MaskOptional(), operands.Span())}; |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, |
|
|
|
@ -626,14 +650,17 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I |
|
|
|
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
|
|
|
Id derivatives, const IR::Value& offset, Id lod_clamp) { |
|
|
|
const auto info{inst->Flags<IR::TextureInstInfo>()}; |
|
|
|
const bool is_integer{IsTextureInteger(ctx, info)}; |
|
|
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; |
|
|
|
const auto operands = info.num_derivatives == 3 |
|
|
|
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, |
|
|
|
ctx.Def(offset), {}, lod_clamp) |
|
|
|
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, |
|
|
|
info.num_derivatives, offset, lod_clamp); |
|
|
|
return Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], |
|
|
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); |
|
|
|
const Id color{Emit(&EmitContext::OpImageSparseSampleExplicitLod, |
|
|
|
&EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, |
|
|
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span())}; |
|
|
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], color) : color; |
|
|
|
} |
|
|
|
|
|
|
|
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) { |
|
|
|
|