mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-02 02:58:46 +00:00
[shader_recompiler] Added texture type functions
This commit is contained in:
@@ -260,6 +260,13 @@ bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) {
|
|||||||
return ctx.textures.at(info.descriptor_index).is_multisample;
|
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) {
|
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||||
if (info.relaxed_precision != 0) {
|
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 EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
Id bias_lc, const IR::Value& offset) {
|
Id bias_lc, const IR::Value& offset) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
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) {
|
if (ctx.stage == Stage::Fragment) {
|
||||||
const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0,
|
const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0,
|
||||||
bias_lc, offset);
|
bias_lc, offset);
|
||||||
return Emit(&EmitContext::OpImageSparseSampleImplicitLod,
|
color = Emit(&EmitContext::OpImageSparseSampleImplicitLod,
|
||||||
&EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4],
|
&EmitContext::OpImageSampleImplicitLod, ctx, inst, result_type,
|
||||||
Texture(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
Texture(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
||||||
} else {
|
} else {
|
||||||
// We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as
|
// 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
|
// derivatives
|
||||||
const Id lod{ctx.Const(0.0f)};
|
const Id lod{ctx.Const(0.0f)};
|
||||||
const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset);
|
const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset);
|
||||||
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
color = 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());
|
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 EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
Id lod, const IR::Value& offset) {
|
Id lod, const IR::Value& offset) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
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);
|
const ImageOperands operands(ctx, false, true, false, lod, offset);
|
||||||
|
|
||||||
Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
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());
|
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
||||||
#ifdef __ANDROID__
|
#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));
|
result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return is_integer ? ctx.OpBitcast(ctx.F32[4], result) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
|
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,
|
Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
const IR::Value& offset, const IR::Value& offset2) {
|
const IR::Value& offset, const IR::Value& offset2) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
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);
|
const ImageOperands operands(ctx, offset, offset2);
|
||||||
if (ctx.profile.need_gather_subpixel_offset) {
|
if (ctx.profile.need_gather_subpixel_offset) {
|
||||||
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
|
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
|
||||||
}
|
}
|
||||||
return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
|
const Id color{Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst,
|
||||||
ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component),
|
result_type, Texture(ctx, info, index), coords,
|
||||||
operands.MaskOptional(), operands.Span());
|
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,
|
Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
const IR::Value& offset, const IR::Value& offset2, Id dref) {
|
const IR::Value& offset, const IR::Value& offset2, Id dref) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
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);
|
const ImageOperands operands(ctx, offset, offset2);
|
||||||
if (ctx.profile.need_gather_subpixel_offset) {
|
if (ctx.profile.need_gather_subpixel_offset) {
|
||||||
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
|
coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords);
|
||||||
}
|
}
|
||||||
return Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather, ctx, inst,
|
const Id color{Emit(&EmitContext::OpImageSparseDrefGather, &EmitContext::OpImageDrefGather,
|
||||||
ctx.F32[4], Texture(ctx, info, index), coords, dref, operands.MaskOptional(),
|
ctx, inst, result_type, Texture(ctx, info, index), coords, dref,
|
||||||
operands.Span());
|
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 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>()};
|
||||||
|
const bool is_integer{IsTextureInteger(ctx, info)};
|
||||||
|
const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
|
||||||
AddOffsetToCoordinates(ctx, info, coords, offset);
|
AddOffsetToCoordinates(ctx, info, coords, offset);
|
||||||
if (info.type == TextureType::Buffer) {
|
if (info.type == TextureType::Buffer) {
|
||||||
lod = Id{};
|
lod = Id{};
|
||||||
@@ -580,8 +602,10 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
|
|||||||
lod = Id{};
|
lod = Id{};
|
||||||
}
|
}
|
||||||
const ImageOperands operands(lod, ms);
|
const ImageOperands operands(lod, ms);
|
||||||
return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
|
const Id color{Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst,
|
||||||
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
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,
|
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 EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||||
Id derivatives, const IR::Value& 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 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
|
const auto operands = info.num_derivatives == 3
|
||||||
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
||||||
ctx.Def(offset), {}, lod_clamp)
|
ctx.Def(offset), {}, lod_clamp)
|
||||||
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
||||||
info.num_derivatives, offset, lod_clamp);
|
info.num_derivatives, offset, lod_clamp);
|
||||||
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
const Id color{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());
|
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) {
|
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ enum class Operation {
|
|||||||
|
|
||||||
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
|
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
|
||||||
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
const spv::ImageFormat format{spv::ImageFormat::Unknown};
|
||||||
const Id type{ctx.F32[1]};
|
const Id type{desc.is_integer ? ctx.U32[1] : ctx.F32[1]};
|
||||||
const bool depth{desc.is_depth};
|
const bool depth{desc.is_depth};
|
||||||
const bool ms{desc.is_multisample};
|
const bool ms{desc.is_multisample};
|
||||||
switch (desc.type) {
|
switch (desc.type) {
|
||||||
@@ -1375,6 +1375,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in
|
|||||||
.image_type = image_type,
|
.image_type = image_type,
|
||||||
.count = desc.count,
|
.count = desc.count,
|
||||||
.is_multisample = desc.is_multisample,
|
.is_multisample = desc.is_multisample,
|
||||||
|
.is_integer = desc.is_integer,
|
||||||
});
|
});
|
||||||
if (profile.supported_spirv >= 0x00010400) {
|
if (profile.supported_spirv >= 0x00010400) {
|
||||||
interfaces.push_back(id);
|
interfaces.push_back(id);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ struct TextureDefinition {
|
|||||||
Id image_type;
|
Id image_type;
|
||||||
u32 count;
|
u32 count;
|
||||||
bool is_multisample;
|
bool is_multisample;
|
||||||
|
bool is_integer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureBufferDefinition {
|
struct TextureBufferDefinition {
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -43,6 +46,10 @@ union TextureInstInfo {
|
|||||||
BitField<25, 2, u32> num_derivatives;
|
BitField<25, 2, u32> num_derivatives;
|
||||||
BitField<27, 3, ImageFormat> image_format;
|
BitField<27, 3, ImageFormat> image_format;
|
||||||
BitField<30, 1, u32> ndv_is_active;
|
BitField<30, 1, u32> ndv_is_active;
|
||||||
|
/// Only meaningful for the sampled-texture family (ImageSampleImplicitLod, ImageFetch,
|
||||||
|
/// ImageGather, etc.); unused/zero for storage-image opcodes, which carry their own
|
||||||
|
/// is_integer via ImageDescriptor/ImageBufferDescriptor instead.
|
||||||
|
BitField<31, 1, u32> is_integer;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(TextureInstInfo) <= sizeof(u32));
|
static_assert(sizeof(TextureInstInfo) <= sizeof(u32));
|
||||||
|
|
||||||
|
|||||||
@@ -562,6 +562,7 @@ public:
|
|||||||
})};
|
})};
|
||||||
// TODO: Read this from TIC
|
// TODO: Read this from TIC
|
||||||
texture_descriptors[index].is_multisample |= desc.is_multisample;
|
texture_descriptors[index].is_multisample |= desc.is_multisample;
|
||||||
|
texture_descriptors[index].is_integer |= desc.is_integer;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,10 +792,12 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
count = std::min(count, sampled_dynamic_cap);
|
count = std::min(count, sampled_dynamic_cap);
|
||||||
|
const bool is_integer{IsTexturePixelFormatIntegerCached(env, cbuf)};
|
||||||
index = descriptors.Add(TextureDescriptor{
|
index = descriptors.Add(TextureDescriptor{
|
||||||
.type = flags.type,
|
.type = flags.type,
|
||||||
.is_depth = flags.is_depth != 0,
|
.is_depth = flags.is_depth != 0,
|
||||||
.is_multisample = is_multisample,
|
.is_multisample = is_multisample,
|
||||||
|
.is_integer = is_integer,
|
||||||
.has_secondary = cbuf.has_secondary,
|
.has_secondary = cbuf.has_secondary,
|
||||||
.cbuf_index = cbuf.index,
|
.cbuf_index = cbuf.index,
|
||||||
.cbuf_offset = cbuf.offset,
|
.cbuf_offset = cbuf.offset,
|
||||||
@@ -805,6 +808,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
|
|||||||
.count = count,
|
.count = count,
|
||||||
.size_shift = size_shift,
|
.size_shift = size_shift,
|
||||||
});
|
});
|
||||||
|
flags.is_integer.Assign(is_integer ? 1 : 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ struct TextureDescriptor {
|
|||||||
TextureType type;
|
TextureType type;
|
||||||
bool is_depth;
|
bool is_depth;
|
||||||
bool is_multisample;
|
bool is_multisample;
|
||||||
|
bool is_integer;
|
||||||
bool has_secondary;
|
bool has_secondary;
|
||||||
u32 cbuf_index;
|
u32 cbuf_index;
|
||||||
u32 cbuf_offset;
|
u32 cbuf_offset;
|
||||||
|
|||||||
Reference in New Issue
Block a user