mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-06 01:12:33 +00:00
shader_recompiler: Check da flag for all mimg instructions.
This commit is contained in:
parent
c05e48becb
commit
120e6ea28f
@ -259,6 +259,14 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
|
|||||||
ctx.AddCapability(spv::Capability::ImageReadWriteLodAMD);
|
ctx.AddCapability(spv::Capability::ImageReadWriteLodAMD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (info.has_cube_arrays) {
|
||||||
|
if (info.has_storage_cube_arrays) {
|
||||||
|
// Implies SampledCubeArray
|
||||||
|
ctx.AddCapability(spv::Capability::ImageCubeArray);
|
||||||
|
} else {
|
||||||
|
ctx.AddCapability(spv::Capability::SampledCubeArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (info.has_texel_buffers) {
|
if (info.has_texel_buffers) {
|
||||||
ctx.AddCapability(spv::Capability::SampledBuffer);
|
ctx.AddCapability(spv::Capability::SampledBuffer);
|
||||||
}
|
}
|
||||||
|
@ -185,12 +185,17 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod
|
|||||||
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
|
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
|
||||||
case AmdGpu::ImageType::Color1DArray:
|
case AmdGpu::ImageType::Color1DArray:
|
||||||
case AmdGpu::ImageType::Color2D:
|
case AmdGpu::ImageType::Color2D:
|
||||||
case AmdGpu::ImageType::Cube:
|
|
||||||
case AmdGpu::ImageType::Color2DMsaa:
|
case AmdGpu::ImageType::Color2DMsaa:
|
||||||
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
|
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
|
||||||
case AmdGpu::ImageType::Color2DArray:
|
case AmdGpu::ImageType::Color2DArray:
|
||||||
case AmdGpu::ImageType::Color3D:
|
case AmdGpu::ImageType::Color3D:
|
||||||
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips());
|
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips());
|
||||||
|
case AmdGpu::ImageType::Cube:
|
||||||
|
// Cube arrays do not have their own type to distinguish by.
|
||||||
|
if (texture.is_array) {
|
||||||
|
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips());
|
||||||
|
}
|
||||||
|
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
|
||||||
default:
|
default:
|
||||||
UNREACHABLE_MSG("SPIR-V Instruction");
|
UNREACHABLE_MSG("SPIR-V Instruction");
|
||||||
}
|
}
|
||||||
|
@ -820,6 +820,7 @@ void EmitContext::DefineImagesAndSamplers() {
|
|||||||
.bound_type = image_desc.GetBoundType(sharp),
|
.bound_type = image_desc.GetBoundType(sharp),
|
||||||
.is_integer = is_integer,
|
.is_integer = is_integer,
|
||||||
.is_storage = is_storage,
|
.is_storage = is_storage,
|
||||||
|
.is_array = image_desc.is_array,
|
||||||
});
|
});
|
||||||
interfaces.push_back(id);
|
interfaces.push_back(id);
|
||||||
}
|
}
|
||||||
|
@ -225,6 +225,7 @@ public:
|
|||||||
AmdGpu::ImageType bound_type;
|
AmdGpu::ImageType bound_type;
|
||||||
bool is_integer = false;
|
bool is_integer = false;
|
||||||
bool is_storage = false;
|
bool is_storage = false;
|
||||||
|
bool is_array = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BufferDefinition {
|
struct BufferDefinition {
|
||||||
|
@ -418,6 +418,7 @@ 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);
|
||||||
|
info.is_array.Assign(mimg.da);
|
||||||
const IR::Value texel = ir.ImageRead(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++) {
|
||||||
@ -442,6 +443,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
|
|||||||
|
|
||||||
IR::TextureInstInfo info{};
|
IR::TextureInstInfo info{};
|
||||||
info.has_lod.Assign(has_mip);
|
info.has_lod.Assign(has_mip);
|
||||||
|
info.is_array.Assign(mimg.da);
|
||||||
|
|
||||||
boost::container::static_vector<IR::F32, 4> comps;
|
boost::container::static_vector<IR::F32, 4> comps;
|
||||||
for (u32 i = 0; i < 4; i++) {
|
for (u32 i = 0; i < 4; i++) {
|
||||||
@ -456,13 +458,18 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
|
void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
|
||||||
|
const auto& mimg = inst.control.mimg;
|
||||||
IR::VectorReg dst_reg{inst.dst[0].code};
|
IR::VectorReg dst_reg{inst.dst[0].code};
|
||||||
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
||||||
const auto flags = ImageResFlags(inst.control.mimg.dmask);
|
const auto flags = ImageResFlags(inst.control.mimg.dmask);
|
||||||
const bool has_mips = flags.test(ImageResComponent::MipCount);
|
const bool has_mips = flags.test(ImageResComponent::MipCount);
|
||||||
const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code));
|
const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code));
|
||||||
const IR::Value tsharp = ir.GetScalarReg(tsharp_reg);
|
const IR::Value tsharp = ir.GetScalarReg(tsharp_reg);
|
||||||
const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips));
|
|
||||||
|
IR::TextureInstInfo info{};
|
||||||
|
info.is_array.Assign(mimg.da);
|
||||||
|
|
||||||
|
const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips), info);
|
||||||
|
|
||||||
if (flags.test(ImageResComponent::Width)) {
|
if (flags.test(ImageResComponent::Width)) {
|
||||||
ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)});
|
ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)});
|
||||||
@ -484,6 +491,9 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
|
|||||||
IR::VectorReg addr_reg{inst.src[0].code};
|
IR::VectorReg addr_reg{inst.src[0].code};
|
||||||
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
||||||
|
|
||||||
|
IR::TextureInstInfo info{};
|
||||||
|
info.is_array.Assign(mimg.da);
|
||||||
|
|
||||||
const IR::Value value = ir.GetVectorReg(val_reg);
|
const IR::Value value = ir.GetVectorReg(val_reg);
|
||||||
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
|
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
|
||||||
const IR::Value body =
|
const IR::Value body =
|
||||||
@ -494,25 +504,25 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
|
|||||||
case AtomicOp::Swap:
|
case AtomicOp::Swap:
|
||||||
return ir.ImageAtomicExchange(handle, body, value, {});
|
return ir.ImageAtomicExchange(handle, body, value, {});
|
||||||
case AtomicOp::Add:
|
case AtomicOp::Add:
|
||||||
return ir.ImageAtomicIAdd(handle, body, value, {});
|
return ir.ImageAtomicIAdd(handle, body, value, info);
|
||||||
case AtomicOp::Smin:
|
case AtomicOp::Smin:
|
||||||
return ir.ImageAtomicIMin(handle, body, value, true, {});
|
return ir.ImageAtomicIMin(handle, body, value, true, info);
|
||||||
case AtomicOp::Umin:
|
case AtomicOp::Umin:
|
||||||
return ir.ImageAtomicUMin(handle, body, value, {});
|
return ir.ImageAtomicUMin(handle, body, value, info);
|
||||||
case AtomicOp::Smax:
|
case AtomicOp::Smax:
|
||||||
return ir.ImageAtomicIMax(handle, body, value, true, {});
|
return ir.ImageAtomicIMax(handle, body, value, true, info);
|
||||||
case AtomicOp::Umax:
|
case AtomicOp::Umax:
|
||||||
return ir.ImageAtomicUMax(handle, body, value, {});
|
return ir.ImageAtomicUMax(handle, body, value, info);
|
||||||
case AtomicOp::And:
|
case AtomicOp::And:
|
||||||
return ir.ImageAtomicAnd(handle, body, value, {});
|
return ir.ImageAtomicAnd(handle, body, value, info);
|
||||||
case AtomicOp::Or:
|
case AtomicOp::Or:
|
||||||
return ir.ImageAtomicOr(handle, body, value, {});
|
return ir.ImageAtomicOr(handle, body, value, info);
|
||||||
case AtomicOp::Xor:
|
case AtomicOp::Xor:
|
||||||
return ir.ImageAtomicXor(handle, body, value, {});
|
return ir.ImageAtomicXor(handle, body, value, info);
|
||||||
case AtomicOp::Inc:
|
case AtomicOp::Inc:
|
||||||
return ir.ImageAtomicInc(handle, body, value, {});
|
return ir.ImageAtomicInc(handle, body, value, info);
|
||||||
case AtomicOp::Dec:
|
case AtomicOp::Dec:
|
||||||
return ir.ImageAtomicDec(handle, body, value, {});
|
return ir.ImageAtomicDec(handle, body, value, info);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -643,11 +653,14 @@ void Translator::IMAGE_GET_LOD(const GcnInst& inst) {
|
|||||||
IR::VectorReg addr_reg{inst.src[0].code};
|
IR::VectorReg addr_reg{inst.src[0].code};
|
||||||
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
|
||||||
|
|
||||||
|
IR::TextureInstInfo info{};
|
||||||
|
info.is_array.Assign(mimg.da);
|
||||||
|
|
||||||
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
|
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
|
||||||
const IR::Value body = ir.CompositeConstruct(
|
const IR::Value body = ir.CompositeConstruct(
|
||||||
ir.GetVectorReg<IR::F32>(addr_reg), ir.GetVectorReg<IR::F32>(addr_reg + 1),
|
ir.GetVectorReg<IR::F32>(addr_reg), ir.GetVectorReg<IR::F32>(addr_reg + 1),
|
||||||
ir.GetVectorReg<IR::F32>(addr_reg + 2), ir.GetVectorReg<IR::F32>(addr_reg + 3));
|
ir.GetVectorReg<IR::F32>(addr_reg + 2), ir.GetVectorReg<IR::F32>(addr_reg + 3));
|
||||||
const IR::Value lod = ir.ImageQueryLod(handle, body, {});
|
const IR::Value lod = ir.ImageQueryLod(handle, body, info);
|
||||||
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)});
|
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)});
|
||||||
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)});
|
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)});
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ struct ImageResource {
|
|||||||
bool is_read{};
|
bool is_read{};
|
||||||
bool is_written{};
|
bool is_written{};
|
||||||
|
|
||||||
AmdGpu::ImageType GetBoundType(const AmdGpu::Image& image) const noexcept {
|
[[nodiscard]] AmdGpu::ImageType GetBoundType(const AmdGpu::Image& image) const noexcept {
|
||||||
const auto base_type = image.GetType();
|
const auto base_type = image.GetType();
|
||||||
if (base_type == AmdGpu::ImageType::Color1DArray && !is_array) {
|
if (base_type == AmdGpu::ImageType::Color1DArray && !is_array) {
|
||||||
return AmdGpu::ImageType::Color1D;
|
return AmdGpu::ImageType::Color1D;
|
||||||
@ -206,6 +206,8 @@ struct Info {
|
|||||||
u64 pgm_hash{};
|
u64 pgm_hash{};
|
||||||
VAddr pgm_base;
|
VAddr pgm_base;
|
||||||
bool has_storage_images{};
|
bool has_storage_images{};
|
||||||
|
bool has_cube_arrays{};
|
||||||
|
bool has_storage_cube_arrays{};
|
||||||
bool has_image_buffers{};
|
bool has_image_buffers{};
|
||||||
bool has_texel_buffers{};
|
bool has_texel_buffers{};
|
||||||
bool has_discard{};
|
bool has_discard{};
|
||||||
|
@ -1732,11 +1732,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::ImageQueryDimension(const Value& handle, const IR::U32& lod,
|
|
||||||
const IR::U1& skip_mips) {
|
|
||||||
return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips);
|
|
||||||
}
|
|
||||||
|
|
||||||
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, TextureInstInfo info) {
|
const IR::U1& skip_mips, TextureInstInfo info) {
|
||||||
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips);
|
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips);
|
||||||
|
@ -324,8 +324,6 @@ public:
|
|||||||
const F32& dref, const F32& lod,
|
const F32& dref, const F32& lod,
|
||||||
const Value& offset, TextureInstInfo info);
|
const Value& offset, TextureInstInfo info);
|
||||||
|
|
||||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod,
|
|
||||||
const U1& skip_mips);
|
|
||||||
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod,
|
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod,
|
||||||
const U1& skip_mips, TextureInstInfo info);
|
const U1& skip_mips, TextureInstInfo info);
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ public:
|
|||||||
|
|
||||||
u32 Add(const ImageResource& desc) {
|
u32 Add(const ImageResource& desc) {
|
||||||
const u32 index{Add(image_resources, desc, [&desc](const auto& existing) {
|
const u32 index{Add(image_resources, desc, [&desc](const auto& existing) {
|
||||||
return desc.sharp_idx == existing.sharp_idx;
|
return desc.sharp_idx == existing.sharp_idx && desc.is_array == existing.is_array;
|
||||||
})};
|
})};
|
||||||
auto& image = image_resources[index];
|
auto& image = image_resources[index];
|
||||||
image.is_read |= desc.is_read;
|
image.is_read |= desc.is_read;
|
||||||
@ -691,7 +691,8 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
|
|||||||
// Query dimensions of image if needed for normalization.
|
// Query dimensions of image if needed for normalization.
|
||||||
// We can't use the image sharp because it could be bound to a different image later.
|
// We can't use the image sharp because it could be bound to a different image later.
|
||||||
const auto dimensions =
|
const auto dimensions =
|
||||||
unnormalized ? ir.ImageQueryDimension(handle, ir.Imm32(0u), ir.Imm1(false)) : IR::Value{};
|
unnormalized ? ir.ImageQueryDimension(handle, ir.Imm32(0u), ir.Imm1(false), inst_info)
|
||||||
|
: IR::Value{};
|
||||||
const auto get_coord = [&](u32 coord_idx, u32 dim_idx) -> IR::Value {
|
const auto get_coord = [&](u32 coord_idx, u32 dim_idx) -> IR::Value {
|
||||||
const auto coord = get_addr_reg(coord_idx);
|
const auto coord = get_addr_reg(coord_idx);
|
||||||
if (unnormalized) {
|
if (unnormalized) {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace Shader::Optimization {
|
namespace Shader::Optimization {
|
||||||
|
|
||||||
void Visit(Info& info, IR::Inst& inst) {
|
void Visit(Info& info, const IR::Inst& inst) {
|
||||||
switch (inst.GetOpcode()) {
|
switch (inst.GetOpcode()) {
|
||||||
case IR::Opcode::GetAttribute:
|
case IR::Opcode::GetAttribute:
|
||||||
case IR::Opcode::GetAttributeU32:
|
case IR::Opcode::GetAttributeU32:
|
||||||
@ -87,6 +87,16 @@ void Visit(Info& info, IR::Inst& inst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisitImage(Info& info, const ImageResource& image) {
|
||||||
|
const auto sharp = image.GetSharp(info);
|
||||||
|
if (image.GetBoundType(sharp) == AmdGpu::ImageType::Cube && image.is_array) {
|
||||||
|
info.has_cube_arrays = true;
|
||||||
|
if (image.IsStorage(sharp)) {
|
||||||
|
info.has_storage_cube_arrays = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CollectShaderInfoPass(IR::Program& program) {
|
void CollectShaderInfoPass(IR::Program& program) {
|
||||||
Info& info{program.info};
|
Info& info{program.info};
|
||||||
for (IR::Block* const block : program.post_order_blocks) {
|
for (IR::Block* const block : program.post_order_blocks) {
|
||||||
@ -94,6 +104,9 @@ void CollectShaderInfoPass(IR::Program& program) {
|
|||||||
Visit(info, inst);
|
Visit(info, inst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto& image : program.info.images) {
|
||||||
|
VisitImage(info, image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Optimization
|
} // namespace Shader::Optimization
|
||||||
|
Loading…
Reference in New Issue
Block a user