mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-13 05:05:57 +00:00
Implement IMAGE_ATOMIC_FMIN and IMAGE_ATOMIC_FMAX for 32bit floats (#2820)
* Implement IMAGE_ATOMIC_FMIN and IMAGE_ATOMIC_FMAX for 32bit floats * Handle missing VK_EXT_shader_atomic_float2
This commit is contained in:
parent
a3bbf2274f
commit
c08f92aca1
16 changed files with 106 additions and 2 deletions
|
@ -270,6 +270,10 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
|
|||
if (info.has_image_query) {
|
||||
ctx.AddCapability(spv::Capability::ImageQuery);
|
||||
}
|
||||
if (info.uses_atomic_float_min_max) {
|
||||
ctx.AddExtension("SPV_EXT_shader_atomic_float_min_max");
|
||||
ctx.AddCapability(spv::Capability::AtomicFloat32MinMaxEXT);
|
||||
}
|
||||
if (info.uses_lane_id) {
|
||||
ctx.AddCapability(spv::Capability::GroupNonUniform);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,14 @@ Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id va
|
|||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
|
||||
}
|
||||
|
||||
Id ImageAtomicF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value,
|
||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
|
||||
const auto& texture = ctx.images[handle & 0xFFFF];
|
||||
const Id pointer{ctx.OpImageTexelPointer(ctx.image_f32, texture.id, coords, ctx.ConstU32(0U))};
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return (ctx.*atomic_func)(ctx.F32[1], pointer, scope, semantics, value);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
Id EmitSharedAtomicIAdd32(EmitContext& ctx, Id offset, Id value) {
|
||||
|
@ -187,6 +195,40 @@ Id EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords
|
|||
return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicUMax);
|
||||
}
|
||||
|
||||
Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value) {
|
||||
if (ctx.profile.supports_image_fp32_atomic_min_max) {
|
||||
return ImageAtomicF32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicFMax);
|
||||
}
|
||||
|
||||
const auto u32_value = ctx.OpBitcast(ctx.U32[1], value);
|
||||
const auto sign_bit_set =
|
||||
ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u));
|
||||
|
||||
const auto result = ctx.OpSelect(
|
||||
ctx.F32[1], sign_bit_set,
|
||||
EmitBitCastF32U32(ctx, EmitImageAtomicUMin32(ctx, inst, handle, coords, u32_value)),
|
||||
EmitBitCastF32U32(ctx, EmitImageAtomicSMax32(ctx, inst, handle, coords, u32_value)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value) {
|
||||
if (ctx.profile.supports_image_fp32_atomic_min_max) {
|
||||
return ImageAtomicF32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicFMin);
|
||||
}
|
||||
|
||||
const auto u32_value = ctx.OpBitcast(ctx.U32[1], value);
|
||||
const auto sign_bit_set =
|
||||
ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u));
|
||||
|
||||
const auto result = ctx.OpSelect(
|
||||
ctx.F32[1], sign_bit_set,
|
||||
EmitBitCastF32U32(ctx, EmitImageAtomicUMax32(ctx, inst, handle, coords, u32_value)),
|
||||
EmitBitCastF32U32(ctx, EmitImageAtomicSMin32(ctx, inst, handle, coords, u32_value)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Id EmitImageAtomicInc32(EmitContext&, IR::Inst*, u32, Id, Id) {
|
||||
// TODO: This is not yet implemented
|
||||
throw NotImplementedException("SPIR-V Instruction");
|
||||
|
|
|
@ -482,6 +482,8 @@ Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords
|
|||
Id EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||
|
|
|
@ -869,6 +869,7 @@ void EmitContext::DefineImagesAndSamplers() {
|
|||
}
|
||||
if (std::ranges::any_of(info.images, &ImageResource::is_atomic)) {
|
||||
image_u32 = TypePointer(spv::StorageClass::Image, U32[1]);
|
||||
image_f32 = TypePointer(spv::StorageClass::Image, F32[1]);
|
||||
}
|
||||
if (info.samplers.empty()) {
|
||||
return;
|
||||
|
|
|
@ -207,6 +207,7 @@ public:
|
|||
Id invocation_id{};
|
||||
Id subgroup_local_invocation_id{};
|
||||
Id image_u32{};
|
||||
Id image_f32{};
|
||||
|
||||
Id shared_memory_u8{};
|
||||
Id shared_memory_u16{};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue