shader_recompiler: Rework image read/write emit. (#1819)
Some checks are pending
Build and Release / get-info (push) Waiting to run
Build and Release / pre-release (push) Blocked by required conditions
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions

This commit is contained in:
squidbus 2024-12-24 15:13:32 -08:00 committed by GitHub
parent 95638d5ca5
commit a89c29c2ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 88 additions and 88 deletions

View file

@ -168,22 +168,6 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords,
return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texels) : texels; return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texels) : texels;
} }
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod,
const IR::Value& offset, Id ms) {
const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id);
const Id result_type = texture.data_types->Get(4);
ImageOperands operands;
operands.AddOffset(ctx, offset);
operands.Add(spv::ImageOperandsMask::Lod, lod);
operands.Add(spv::ImageOperandsMask::Sample, ms);
const Id texel =
texture.is_storage
? ctx.OpImageRead(result_type, image, coords, operands.mask, operands.operands)
: ctx.OpImageFetch(result_type, image, coords, operands.mask, operands.operands);
return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], texel) : texel;
}
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool has_mips) { Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool has_mips) {
const auto& texture = ctx.images[handle & 0xFFFF]; const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id); const Id image = ctx.OpLoad(texture.image_type, texture.id);
@ -236,15 +220,34 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id
return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample; return texture.is_integer ? ctx.OpBitcast(ctx.F32[4], sample) : sample;
} }
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id lod) { Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms) {
UNREACHABLE_MSG("SPIR-V Instruction");
}
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id color) {
const auto& texture = ctx.images[handle & 0xFFFF]; const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id); const Id image = ctx.OpLoad(texture.image_type, texture.id);
const Id color_type = texture.data_types->Get(4); const Id color_type = texture.data_types->Get(4);
ImageOperands operands; ImageOperands operands;
operands.Add(spv::ImageOperandsMask::Sample, ms);
Id texel;
if (!texture.is_storage) {
operands.Add(spv::ImageOperandsMask::Lod, lod);
texel = ctx.OpImageFetch(color_type, image, coords, operands.mask, operands.operands);
} else {
if (ctx.profile.supports_image_load_store_lod) {
operands.Add(spv::ImageOperandsMask::Lod, lod);
} else if (Sirit::ValidId(lod)) {
LOG_WARNING(Render, "Image read with LOD not supported by driver");
}
texel = ctx.OpImageRead(color_type, image, coords, operands.mask, operands.operands);
}
return !texture.is_integer ? ctx.OpBitcast(ctx.U32[4], texel) : texel;
}
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms,
Id color) {
const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id);
const Id color_type = texture.data_types->Get(4);
ImageOperands operands;
operands.Add(spv::ImageOperandsMask::Sample, ms);
if (ctx.profile.supports_image_load_store_lod) { if (ctx.profile.supports_image_load_store_lod) {
operands.Add(spv::ImageOperandsMask::Lod, lod); operands.Add(spv::ImageOperandsMask::Lod, lod);
} else if (Sirit::ValidId(lod)) { } else if (Sirit::ValidId(lod)) {

View file

@ -395,14 +395,13 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords,
const IR::Value& offset); const IR::Value& offset);
Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords,
const IR::Value& offset, Id dref); const IR::Value& offset, Id dref);
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod,
const IR::Value& offset, Id ms);
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips);
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords); Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords);
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx, Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx,
Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp); Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp);
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id lod); Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms);
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id color); void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms,
Id color);
Id EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); Id EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);

View file

@ -772,7 +772,7 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
const auto image = desc.GetSharp(ctx.info); const auto image = desc.GetSharp(ctx.info);
const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown;
const auto type = image.GetBoundType(); const auto type = image.GetBoundType();
const u32 sampled = desc.is_storage ? 2 : 1; const u32 sampled = desc.IsStorage(image) ? 2 : 1;
switch (type) { switch (type) {
case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format); return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format);
@ -800,6 +800,7 @@ void EmitContext::DefineImagesAndSamplers() {
const auto sharp = image_desc.GetSharp(info); const auto sharp = image_desc.GetSharp(info);
const auto nfmt = sharp.GetNumberFmt(); const auto nfmt = sharp.GetNumberFmt();
const bool is_integer = AmdGpu::IsInteger(nfmt); const bool is_integer = AmdGpu::IsInteger(nfmt);
const bool is_storage = image_desc.IsStorage(sharp);
const VectorIds& data_types = GetAttributeType(*this, nfmt); const VectorIds& data_types = GetAttributeType(*this, nfmt);
const Id sampled_type = data_types[1]; const Id sampled_type = data_types[1];
const Id image_type{ImageType(*this, image_desc, sampled_type)}; const Id image_type{ImageType(*this, image_desc, sampled_type)};
@ -811,11 +812,11 @@ void EmitContext::DefineImagesAndSamplers() {
images.push_back({ images.push_back({
.data_types = &data_types, .data_types = &data_types,
.id = id, .id = id,
.sampled_type = image_desc.is_storage ? sampled_type : TypeSampledImage(image_type), .sampled_type = is_storage ? sampled_type : TypeSampledImage(image_type),
.pointer_type = pointer_type, .pointer_type = pointer_type,
.image_type = image_type, .image_type = image_type,
.is_integer = is_integer, .is_integer = is_integer,
.is_storage = image_desc.is_storage, .is_storage = is_storage,
}); });
interfaces.push_back(id); interfaces.push_back(id);
} }

View file

@ -420,13 +420,13 @@ void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) {
IR::TextureInstInfo info{}; IR::TextureInstInfo info{};
info.has_lod.Assign(has_mip); info.has_lod.Assign(has_mip);
const IR::Value texel = ir.ImageFetch(handle, body, {}, {}, {}, info); const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info);
for (u32 i = 0; i < 4; i++) { for (u32 i = 0; i < 4; i++) {
if (((mimg.dmask >> i) & 1) == 0) { if (((mimg.dmask >> i) & 1) == 0) {
continue; continue;
} }
IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; IR::U32 value = IR::U32{ir.CompositeExtract(texel, i)};
ir.SetVectorReg(dest_reg++, value); ir.SetVectorReg(dest_reg++, value);
} }
} }
@ -454,7 +454,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
comps.push_back(ir.GetVectorReg<IR::F32>(data_reg++)); comps.push_back(ir.GetVectorReg<IR::F32>(data_reg++));
} }
const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]); const IR::Value value = ir.CompositeConstruct(comps[0], comps[1], comps[2], comps[3]);
ir.ImageWrite(handle, body, {}, value, info); ir.ImageWrite(handle, body, {}, {}, value, info);
} }
void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) { void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {

View file

@ -49,11 +49,11 @@ struct BufferResource {
u8 instance_attrib{}; u8 instance_attrib{};
bool is_written{}; bool is_written{};
bool IsStorage(AmdGpu::Buffer buffer) const noexcept { [[nodiscard]] bool IsStorage(const AmdGpu::Buffer& buffer) const noexcept {
return buffer.GetSize() > MaxUboSize || is_written || is_gds_buffer; return buffer.GetSize() > MaxUboSize || is_written || is_gds_buffer;
} }
constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept;
}; };
using BufferResourceList = boost::container::small_vector<BufferResource, 16>; using BufferResourceList = boost::container::small_vector<BufferResource, 16>;
@ -61,18 +61,24 @@ struct TextureBufferResource {
u32 sharp_idx; u32 sharp_idx;
bool is_written{}; bool is_written{};
constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept; [[nodiscard]] constexpr AmdGpu::Buffer GetSharp(const Info& info) const noexcept;
}; };
using TextureBufferResourceList = boost::container::small_vector<TextureBufferResource, 16>; using TextureBufferResourceList = boost::container::small_vector<TextureBufferResource, 16>;
struct ImageResource { struct ImageResource {
u32 sharp_idx; u32 sharp_idx;
bool is_storage{};
bool is_depth{}; bool is_depth{};
bool is_atomic{}; bool is_atomic{};
bool is_array{}; bool is_array{};
bool is_read{};
bool is_written{};
constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept; [[nodiscard]] bool IsStorage(const AmdGpu::Image& image) const noexcept {
// Need cube as storage when used with ImageRead.
return is_written || (is_read && image.GetBoundType() == AmdGpu::ImageType::Cube);
}
[[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept;
}; };
using ImageResourceList = boost::container::small_vector<ImageResource, 16>; using ImageResourceList = boost::container::small_vector<ImageResource, 16>;

View file

@ -1630,11 +1630,6 @@ Value IREmitter::ImageGatherDref(const Value& handle, const Value& coords, const
return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref); return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref);
} }
Value IREmitter::ImageFetch(const Value& handle, const Value& coords, const U32& lod,
const Value& offset, const U32& multisampling, TextureInstInfo info) {
return Inst(Opcode::ImageFetch, Flags{info}, handle, coords, lod, offset, multisampling);
}
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
const IR::U1& skip_mips) { const IR::U1& skip_mips) {
return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips); return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips);
@ -1657,13 +1652,13 @@ Value IREmitter::ImageGradient(const Value& handle, const Value& coords,
} }
Value IREmitter::ImageRead(const Value& handle, const Value& coords, const U32& lod, Value IREmitter::ImageRead(const Value& handle, const Value& coords, const U32& lod,
TextureInstInfo info) { const U32& multisampling, TextureInstInfo info) {
return Inst(Opcode::ImageRead, Flags{info}, handle, coords, lod); return Inst(Opcode::ImageRead, Flags{info}, handle, coords, lod, multisampling);
} }
void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32& lod, void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32& lod,
const Value& color, TextureInstInfo info) { const U32& multisampling, const Value& color, TextureInstInfo info) {
Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, color); Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, multisampling, color);
} }
// Debug print maps to SPIRV's NonSemantic DebugPrintf instruction // Debug print maps to SPIRV's NonSemantic DebugPrintf instruction

View file

@ -325,17 +325,14 @@ public:
TextureInstInfo info); TextureInstInfo info);
[[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords, [[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords,
const Value& offset, const F32& dref, TextureInstInfo info); const Value& offset, const F32& dref, TextureInstInfo info);
[[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const U32& lod,
const Value& offset, const U32& multisampling,
TextureInstInfo info);
[[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords,
const Value& derivatives_dx, const Value& derivatives_dy, const Value& derivatives_dx, const Value& derivatives_dy,
const Value& offset, const F32& lod_clamp, const Value& offset, const F32& lod_clamp,
TextureInstInfo info); TextureInstInfo info);
[[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, const U32& lod, [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, const U32& lod,
TextureInstInfo info); const U32& multisampling, TextureInstInfo info);
void ImageWrite(const Value& handle, const Value& coords, const U32& lod, const Value& color, void ImageWrite(const Value& handle, const Value& coords, const U32& lod,
TextureInstInfo info); const U32& multisampling, const Value& color, TextureInstInfo info);
void EmitVertex(); void EmitVertex();
void EmitPrimitive(); void EmitPrimitive();

View file

@ -338,12 +338,11 @@ OPCODE(ImageSampleDrefImplicitLod, F32x4, Opaq
OPCODE(ImageSampleDrefExplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) OPCODE(ImageSampleDrefExplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, )
OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, ) OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, )
OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, F32, )
OPCODE(ImageFetch, F32x4, Opaque, Opaque, U32, Opaque, Opaque, )
OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, )
OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, )
OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, )
OPCODE(ImageRead, U32x4, Opaque, Opaque, U32, ) OPCODE(ImageRead, U32x4, Opaque, Opaque, U32, U32, )
OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32x4, ) OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32, U32x4, )
// Image atomic operations // Image atomic operations
OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, )

View file

@ -115,25 +115,16 @@ bool IsImageAtomicInstruction(const IR::Inst& inst) {
} }
} }
bool IsImageStorageInstruction(const IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::ImageWrite:
case IR::Opcode::ImageRead:
return true;
default:
return IsImageAtomicInstruction(inst);
}
}
bool IsImageInstruction(const IR::Inst& inst) { bool IsImageInstruction(const IR::Inst& inst) {
switch (inst.GetOpcode()) { switch (inst.GetOpcode()) {
case IR::Opcode::ImageFetch: case IR::Opcode::ImageRead:
case IR::Opcode::ImageWrite:
case IR::Opcode::ImageQueryDimensions: case IR::Opcode::ImageQueryDimensions:
case IR::Opcode::ImageQueryLod: case IR::Opcode::ImageQueryLod:
case IR::Opcode::ImageSampleRaw: case IR::Opcode::ImageSampleRaw:
return true; return true;
default: default:
return IsImageStorageInstruction(inst); return IsImageAtomicInstruction(inst);
} }
} }
@ -201,7 +192,8 @@ public:
return desc.sharp_idx == existing.sharp_idx; return desc.sharp_idx == existing.sharp_idx;
})}; })};
auto& image = image_resources[index]; auto& image = image_resources[index];
image.is_storage |= desc.is_storage; image.is_read |= desc.is_read;
image.is_written |= desc.is_written;
return index; return index;
} }
@ -429,9 +421,9 @@ void PatchTextureBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
} }
IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t, IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t,
const IR::Value& z, bool is_storage, bool is_array) { const IR::Value& z, bool is_written, bool is_array) {
// When cubemap is written with imageStore it is treated like 2DArray. // When cubemap is written with imageStore it is treated like 2DArray.
if (is_storage) { if (is_written) {
return ir.CompositeConstruct(s, t, z); return ir.CompositeConstruct(s, t, z);
} }
@ -684,15 +676,16 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
image = AmdGpu::Image::Null(); image = AmdGpu::Image::Null();
} }
ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); ASSERT(image.GetType() != AmdGpu::ImageType::Invalid);
const bool is_storage = IsImageStorageInstruction(inst); const bool is_read = inst.GetOpcode() == IR::Opcode::ImageRead;
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite;
// Patch image instruction if image is FMask. // Patch image instruction if image is FMask.
if (image.IsFmask()) { if (image.IsFmask()) {
ASSERT_MSG(!is_storage, "FMask storage instructions are not supported"); ASSERT_MSG(!is_written, "FMask storage instructions are not supported");
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
switch (inst.GetOpcode()) { switch (inst.GetOpcode()) {
case IR::Opcode::ImageFetch: case IR::Opcode::ImageRead:
case IR::Opcode::ImageSampleRaw: { case IR::Opcode::ImageSampleRaw: {
IR::F32 fmaskx = ir.BitCast<IR::F32>(ir.Imm32(0x76543210)); IR::F32 fmaskx = ir.BitCast<IR::F32>(ir.Imm32(0x76543210));
IR::F32 fmasky = ir.BitCast<IR::F32>(ir.Imm32(0xfedcba98)); IR::F32 fmasky = ir.BitCast<IR::F32>(ir.Imm32(0xfedcba98));
@ -721,10 +714,11 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
u32 image_binding = descriptors.Add(ImageResource{ u32 image_binding = descriptors.Add(ImageResource{
.sharp_idx = tsharp, .sharp_idx = tsharp,
.is_storage = is_storage,
.is_depth = bool(inst_info.is_depth), .is_depth = bool(inst_info.is_depth),
.is_atomic = IsImageAtomicInstruction(inst), .is_atomic = IsImageAtomicInstruction(inst),
.is_array = bool(inst_info.is_array), .is_array = bool(inst_info.is_array),
.is_read = is_read,
.is_written = is_written,
}); });
// Sample instructions must be resolved into a new instruction using address register data. // Sample instructions must be resolved into a new instruction using address register data.
@ -762,7 +756,7 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
case AmdGpu::ImageType::Color3D: // x, y, z, [lod] case AmdGpu::ImageType::Color3D: // x, y, z, [lod]
return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)};
case AmdGpu::ImageType::Cube: // x, y, face, [lod] case AmdGpu::ImageType::Cube: // x, y, face, [lod]
return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage, return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_written,
inst_info.is_array), inst_info.is_array),
body->Arg(3)}; body->Arg(3)};
default: default:
@ -772,19 +766,20 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip
inst.SetArg(1, coords); inst.SetArg(1, coords);
if (inst.GetOpcode() == IR::Opcode::ImageWrite) { if (inst.GetOpcode() == IR::Opcode::ImageWrite) {
inst.SetArg(3, SwizzleVector(ir, image, inst.Arg(3))); inst.SetArg(4, SwizzleVector(ir, image, inst.Arg(4)));
} }
if (inst_info.has_lod) { if (inst_info.has_lod) {
ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch || ASSERT(inst.GetOpcode() == IR::Opcode::ImageRead ||
inst.GetOpcode() == IR::Opcode::ImageRead ||
inst.GetOpcode() == IR::Opcode::ImageWrite); inst.GetOpcode() == IR::Opcode::ImageWrite);
ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa && ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa &&
image.GetType() != AmdGpu::ImageType::Color2DMsaaArray); image.GetType() != AmdGpu::ImageType::Color2DMsaaArray);
inst.SetArg(2, arg); inst.SetArg(2, arg);
} else if (image.GetType() == AmdGpu::ImageType::Color2DMsaa || } else if ((image.GetType() == AmdGpu::ImageType::Color2DMsaa ||
image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) { image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) &&
inst.SetArg(4, arg); (inst.GetOpcode() == IR::Opcode::ImageRead ||
inst.GetOpcode() == IR::Opcode::ImageWrite)) {
inst.SetArg(3, arg);
} }
} }

View file

@ -39,10 +39,12 @@ struct TextureBufferSpecialization {
struct ImageSpecialization { struct ImageSpecialization {
AmdGpu::ImageType type = AmdGpu::ImageType::Color2D; AmdGpu::ImageType type = AmdGpu::ImageType::Color2D;
bool is_integer = false; bool is_integer = false;
bool is_storage = false;
u32 dst_select = 0; u32 dst_select = 0;
bool operator==(const ImageSpecialization& other) const { bool operator==(const ImageSpecialization& other) const {
return type == other.type && is_integer == other.is_integer && return type == other.type && is_integer == other.is_integer &&
is_storage == other.is_storage &&
(dst_select != 0 ? dst_select == other.dst_select : true); (dst_select != 0 ? dst_select == other.dst_select : true);
} }
}; };
@ -114,7 +116,8 @@ struct StageSpecialization {
[](auto& spec, const auto& desc, AmdGpu::Image sharp) { [](auto& spec, const auto& desc, AmdGpu::Image sharp) {
spec.type = sharp.GetBoundType(); spec.type = sharp.GetBoundType();
spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt()); spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt());
if (desc.is_storage) { spec.is_storage = desc.IsStorage(sharp);
if (spec.is_storage) {
spec.dst_select = sharp.DstSelect(); spec.dst_select = sharp.DstSelect();
} }
}); });

View file

@ -58,8 +58,9 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
for (const auto& image : info->images) { for (const auto& image : info->images) {
bindings.push_back({ bindings.push_back({
.binding = binding++, .binding = binding++,
.descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage .descriptorType = image.IsStorage(image.GetSharp(*info))
: vk::DescriptorType::eSampledImage, ? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1, .descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute, .stageFlags = vk::ShaderStageFlagBits::eCompute,
}); });

View file

@ -378,8 +378,9 @@ void GraphicsPipeline::BuildDescSetLayout() {
for (const auto& image : stage->images) { for (const auto& image : stage->images) {
bindings.push_back({ bindings.push_back({
.binding = binding++, .binding = binding++,
.descriptorType = image.is_storage ? vk::DescriptorType::eStorageImage .descriptorType = image.IsStorage(image.GetSharp(*stage))
: vk::DescriptorType::eSampledImage, ? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1, .descriptorCount = 1,
.stageFlags = gp_stage_flags, .stageFlags = gp_stage_flags,
}); });

View file

@ -655,7 +655,7 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
if (image->binding.is_bound) { if (image->binding.is_bound) {
// The image is already bound. In case if it is about to be used as storage we need // The image is already bound. In case if it is about to be used as storage we need
// to force general layout on it. // to force general layout on it.
image->binding.force_general |= image_desc.is_storage; image->binding.force_general |= image_desc.IsStorage(tsharp);
} }
if (image->binding.is_target) { if (image->binding.is_target) {
// The image is already bound as target. Since we read and output to it need to force // The image is already bound as target. Since we read and output to it need to force

View file

@ -51,7 +51,7 @@ vk::ComponentSwizzle ConvertComponentSwizzle(u32 dst_sel) {
} }
ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept
: is_storage{desc.is_storage} { : is_storage{desc.IsStorage(image)} {
const auto dfmt = image.GetDataFmt(); const auto dfmt = image.GetDataFmt();
auto nfmt = image.GetNumberFmt(); auto nfmt = image.GetNumberFmt();
if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) { if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) {

View file

@ -65,7 +65,7 @@ public:
struct TextureDesc : public BaseDesc { struct TextureDesc : public BaseDesc {
TextureDesc() = default; TextureDesc() = default;
TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc) TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc)
: BaseDesc{desc.is_storage ? BindingType::Storage : BindingType::Texture, : BaseDesc{desc.IsStorage(image) ? BindingType::Storage : BindingType::Texture,
ImageInfo{image, desc}, ImageViewInfo{image, desc}} {} ImageInfo{image, desc}, ImageViewInfo{image, desc}} {}
}; };