Merge pull request #12644 from liamwhite/vkspec-image-offset

shader_recompiler: fix Offset operand usage for non-OpImage*Gather
master
liamwhite 2024-01-18 21:18:19 +07:00 committed by GitHub
commit 97c8b49444
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 23 deletions

@ -12,6 +12,11 @@ namespace Shader::Backend::SPIRV {
namespace { namespace {
class ImageOperands { class ImageOperands {
public: public:
[[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false;
[[maybe_unused]] static constexpr bool ImageGatherOffsetAllowed = true;
[[maybe_unused]] static constexpr bool ImageFetchOffsetAllowed = false;
[[maybe_unused]] static constexpr bool ImageGradientOffsetAllowed = false;
explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp, explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp,
Id lod, const IR::Value& offset) { Id lod, const IR::Value& offset) {
if (has_bias) { if (has_bias) {
@ -22,7 +27,7 @@ public:
const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod}; const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
Add(spv::ImageOperandsMask::Lod, lod_value); Add(spv::ImageOperandsMask::Lod, lod_value);
} }
AddOffset(ctx, offset); AddOffset(ctx, offset, ImageSampleOffsetAllowed);
if (has_lod_clamp) { if (has_lod_clamp) {
const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod}; const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod};
Add(spv::ImageOperandsMask::MinLod, lod_clamp); Add(spv::ImageOperandsMask::MinLod, lod_clamp);
@ -55,20 +60,17 @@ public:
Add(spv::ImageOperandsMask::ConstOffsets, offsets); Add(spv::ImageOperandsMask::ConstOffsets, offsets);
} }
explicit ImageOperands(Id offset, Id lod, Id ms) { explicit ImageOperands(Id lod, Id ms) {
if (Sirit::ValidId(lod)) { if (Sirit::ValidId(lod)) {
Add(spv::ImageOperandsMask::Lod, lod); Add(spv::ImageOperandsMask::Lod, lod);
} }
if (Sirit::ValidId(offset)) {
Add(spv::ImageOperandsMask::Offset, offset);
}
if (Sirit::ValidId(ms)) { if (Sirit::ValidId(ms)) {
Add(spv::ImageOperandsMask::Sample, ms); Add(spv::ImageOperandsMask::Sample, ms);
} }
} }
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives, explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives,
u32 num_derivatives, Id offset, Id lod_clamp) { u32 num_derivatives, const IR::Value& offset, Id lod_clamp) {
if (!Sirit::ValidId(derivatives)) { if (!Sirit::ValidId(derivatives)) {
throw LogicError("Derivatives must be present"); throw LogicError("Derivatives must be present");
} }
@ -83,16 +85,14 @@ public:
const Id derivatives_Y{ctx.OpCompositeConstruct( const Id derivatives_Y{ctx.OpCompositeConstruct(
ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})}; ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})};
Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y); Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y);
if (Sirit::ValidId(offset)) { AddOffset(ctx, offset, ImageGradientOffsetAllowed);
Add(spv::ImageOperandsMask::Offset, offset);
}
if (has_lod_clamp) { if (has_lod_clamp) {
Add(spv::ImageOperandsMask::MinLod, lod_clamp); Add(spv::ImageOperandsMask::MinLod, lod_clamp);
} }
} }
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2, explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2,
Id offset, Id lod_clamp) { const IR::Value& offset, Id lod_clamp) {
if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) { if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) {
throw LogicError("Derivatives must be present"); throw LogicError("Derivatives must be present");
} }
@ -111,9 +111,7 @@ public:
const Id derivatives_id2{ctx.OpCompositeConstruct( const Id derivatives_id2{ctx.OpCompositeConstruct(
ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})}; ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})};
Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2); Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2);
if (Sirit::ValidId(offset)) { AddOffset(ctx, offset, ImageGradientOffsetAllowed);
Add(spv::ImageOperandsMask::Offset, offset);
}
if (has_lod_clamp) { if (has_lod_clamp) {
Add(spv::ImageOperandsMask::MinLod, lod_clamp); Add(spv::ImageOperandsMask::MinLod, lod_clamp);
} }
@ -132,7 +130,7 @@ public:
} }
private: private:
void AddOffset(EmitContext& ctx, const IR::Value& offset) { void AddOffset(EmitContext& ctx, const IR::Value& offset, bool runtime_offset_allowed) {
if (offset.IsEmpty()) { if (offset.IsEmpty()) {
return; return;
} }
@ -165,7 +163,9 @@ private:
break; break;
} }
} }
Add(spv::ImageOperandsMask::Offset, ctx.Def(offset)); if (runtime_offset_allowed) {
Add(spv::ImageOperandsMask::Offset, ctx.Def(offset));
}
} }
void Add(spv::ImageOperandsMask new_mask, Id value) { void Add(spv::ImageOperandsMask new_mask, Id value) {
@ -311,6 +311,37 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info,
return coords; return coords;
} }
} }
void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords,
Id offset) {
if (!Sirit::ValidId(offset)) {
return;
}
Id result_type{};
switch (info.type) {
case TextureType::Buffer:
case TextureType::Color1D:
case TextureType::ColorArray1D: {
result_type = ctx.U32[1];
break;
}
case TextureType::Color2D:
case TextureType::Color2DRect:
case TextureType::ColorArray2D: {
result_type = ctx.U32[2];
break;
}
case TextureType::Color3D: {
result_type = ctx.U32[3];
break;
}
case TextureType::ColorCube:
case TextureType::ColorArrayCube:
return;
}
coords = ctx.OpIAdd(result_type, coords, offset);
}
} // Anonymous namespace } // Anonymous namespace
Id EmitBindlessImageSampleImplicitLod(EmitContext&) { Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
@ -496,6 +527,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
Id lod, Id ms) { Id lod, Id ms) {
const auto info{inst->Flags<IR::TextureInstInfo>()}; const auto info{inst->Flags<IR::TextureInstInfo>()};
AddOffsetToCoordinates(ctx, info, coords, offset);
if (info.type == TextureType::Buffer) { if (info.type == TextureType::Buffer) {
lod = Id{}; lod = Id{};
} }
@ -503,7 +535,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
// This image is multisampled, lod must be implicit // This image is multisampled, lod must be implicit
lod = Id{}; lod = Id{};
} }
const ImageOperands operands(offset, lod, ms); const ImageOperands operands(lod, ms);
return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
} }
@ -548,13 +580,13 @@ 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 EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id derivatives, Id offset, Id lod_clamp) { Id derivatives, const IR::Value& offset, Id lod_clamp) {
const auto info{inst->Flags<IR::TextureInstInfo>()}; const auto info{inst->Flags<IR::TextureInstInfo>()};
const auto operands = const auto operands = info.num_derivatives == 3
info.num_derivatives == 3 ? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp) ctx.Def(offset), {}, lod_clamp)
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
lod_clamp); info.num_derivatives, offset, lod_clamp);
return Emit(&EmitContext::OpImageSparseSampleExplicitLod, return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); Texture(ctx, info, index), coords, operands.Mask(), operands.Span());

@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
const IR::Value& skip_mips); const IR::Value& skip_mips);
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
Id derivatives, Id offset, Id lod_clamp); Id derivatives, const IR::Value& offset, Id lod_clamp);
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color); void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index); Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index);