summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2023-06-06 06:43:43 +0200
committerGitHub <noreply@github.com>2023-06-06 06:43:43 +0200
commitcb95d7fe1b6d81899fe6b279400da2c991e3132c (patch)
treea856ac45b1053009c4c11ee141c49d7faa4c8a19 /src/shader_recompiler
parentMerge pull request #10611 from liamwhite/audio-deadlock (diff)
parentMerge pull request #10633 from t895/variable-surface-ratio (diff)
downloadyuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.gz
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.bz2
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.lz
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.xz
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.zst
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.zip
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp10
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp44
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp17
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp61
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h16
-rw-r--r--src/shader_recompiler/profile.h3
-rw-r--r--src/shader_recompiler/runtime_info.h2
7 files changed, 103 insertions, 50 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
index 4b3043b65..0ce73f289 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp
@@ -69,6 +69,11 @@ Id StorageAtomicU32(EmitContext& ctx, const IR::Value& binding, const IR::Value&
Id StorageAtomicU64(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value,
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id),
Id (Sirit::Module::*non_atomic_func)(Id, Id, Id)) {
+ if (!ctx.profile.support_descriptor_aliasing) {
+ LOG_WARNING(Shader_SPIRV, "Descriptor aliasing not supported, this cannot be atomic.");
+ return ctx.ConstantNull(ctx.U64);
+ }
+
if (ctx.profile.support_int64_atomics) {
const Id pointer{StoragePointer(ctx, ctx.storage_types.U64, &StorageDefinitions::U64,
binding, offset, sizeof(u64))};
@@ -86,6 +91,11 @@ Id StorageAtomicU64(EmitContext& ctx, const IR::Value& binding, const IR::Value&
Id StorageAtomicU32x2(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset, Id value,
Id (Sirit::Module::*non_atomic_func)(Id, Id, Id)) {
+ if (!ctx.profile.support_descriptor_aliasing) {
+ LOG_WARNING(Shader_SPIRV, "Descriptor aliasing not supported, this cannot be atomic.");
+ return ctx.ConstantNull(ctx.U32[2]);
+ }
+
LOG_WARNING(Shader_SPIRV, "Int64 atomics not supported, fallback to non-atomic");
const Id pointer{StoragePointer(ctx, ctx.storage_types.U32x2, &StorageDefinitions::U32x2,
binding, offset, sizeof(u32[2]))};
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 07c2b7b8a..2868fc57d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -10,27 +10,6 @@
namespace Shader::Backend::SPIRV {
namespace {
-struct AttrInfo {
- Id pointer;
- Id id;
- bool needs_cast;
-};
-
-std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) {
- const AttributeType type{ctx.runtime_info.generic_input_types.at(index)};
- switch (type) {
- case AttributeType::Float:
- return AttrInfo{ctx.input_f32, ctx.F32[1], false};
- case AttributeType::UnsignedInt:
- return AttrInfo{ctx.input_u32, ctx.U32[1], true};
- case AttributeType::SignedInt:
- return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true};
- case AttributeType::Disabled:
- return std::nullopt;
- }
- throw InvalidArgument("Invalid attribute type {}", type);
-}
-
template <typename... Args>
Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&... args) {
switch (ctx.stage) {
@@ -302,15 +281,26 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
const u32 element{static_cast<u32>(attr) % 4};
if (IR::IsGeneric(attr)) {
const u32 index{IR::GenericAttributeIndex(attr)};
- const std::optional<AttrInfo> type{AttrTypes(ctx, index)};
- if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index, element)) {
+ const auto& generic{ctx.input_generics.at(index)};
+ if (!ValidId(generic.id)) {
// Attribute is disabled or varying component is not written
return ctx.Const(element == 3 ? 1.0f : 0.0f);
}
- const Id generic_id{ctx.input_generics.at(index)};
- const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))};
- const Id value{ctx.OpLoad(type->id, pointer)};
- return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value;
+ const Id pointer{
+ AttrPointer(ctx, generic.pointer_type, vertex, generic.id, ctx.Const(element))};
+ const Id value{ctx.OpLoad(generic.component_type, pointer)};
+ return [&ctx, generic, value]() {
+ switch (generic.load_op) {
+ case InputGenericLoadOp::Bitcast:
+ return ctx.OpBitcast(ctx.F32[1], value);
+ case InputGenericLoadOp::SToF:
+ return ctx.OpConvertSToF(ctx.F32[1], value);
+ case InputGenericLoadOp::UToF:
+ return ctx.OpConvertUToF(ctx.F32[1], value);
+ default:
+ return value;
+ };
+ }();
}
switch (attr) {
case IR::Attribute::PrimitiveId:
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
index c5db19d09..77ff8c573 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
@@ -17,7 +17,22 @@ Id GetThreadId(EmitContext& ctx) {
Id WarpExtract(EmitContext& ctx, Id value) {
const Id thread_id{GetThreadId(ctx)};
const Id local_index{ctx.OpShiftRightArithmetic(ctx.U32[1], thread_id, ctx.Const(5U))};
- return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index);
+ if (ctx.profile.has_broken_spirv_subgroup_mask_vector_extract_dynamic) {
+ const Id c0_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(0U)),
+ ctx.OpCompositeExtract(ctx.U32[1], value, 0U), ctx.Const(0U))};
+ const Id c1_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(1U)),
+ ctx.OpCompositeExtract(ctx.U32[1], value, 1U), ctx.Const(0U))};
+ const Id c2_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(2U)),
+ ctx.OpCompositeExtract(ctx.U32[1], value, 2U), ctx.Const(0U))};
+ const Id c3_sel{ctx.OpSelect(ctx.U32[1], ctx.OpIEqual(ctx.U1, local_index, ctx.Const(3U)),
+ ctx.OpCompositeExtract(ctx.U32[1], value, 3U), ctx.Const(0U))};
+ const Id c0_or_c1{ctx.OpBitwiseOr(ctx.U32[1], c0_sel, c1_sel)};
+ const Id c2_or_c3{ctx.OpBitwiseOr(ctx.U32[1], c2_sel, c3_sel)};
+ const Id c0_or_c1_or_c2_or_c3{ctx.OpBitwiseOr(ctx.U32[1], c0_or_c1, c2_or_c3)};
+ return c0_or_c1_or_c2_or_c3;
+ } else {
+ return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index);
+ }
}
Id LoadMask(EmitContext& ctx, Id mask) {
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 47739794f..fd15f47ea 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -25,12 +25,6 @@ enum class Operation {
FPMax,
};
-struct AttrInfo {
- Id pointer;
- Id id;
- bool needs_cast;
-};
-
Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
const spv::ImageFormat format{spv::ImageFormat::Unknown};
const Id type{ctx.F32[1]};
@@ -206,23 +200,37 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) {
return ctx.TypeVector(ctx.TypeInt(32, true), 4);
case AttributeType::UnsignedInt:
return ctx.U32[4];
+ case AttributeType::SignedScaled:
+ return ctx.profile.support_scaled_attributes ? ctx.F32[4]
+ : ctx.TypeVector(ctx.TypeInt(32, true), 4);
+ case AttributeType::UnsignedScaled:
+ return ctx.profile.support_scaled_attributes ? ctx.F32[4] : ctx.U32[4];
case AttributeType::Disabled:
break;
}
throw InvalidArgument("Invalid attribute type {}", type);
}
-std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) {
- const AttributeType type{ctx.runtime_info.generic_input_types.at(index)};
+InputGenericInfo GetAttributeInfo(EmitContext& ctx, AttributeType type, Id id) {
switch (type) {
case AttributeType::Float:
- return AttrInfo{ctx.input_f32, ctx.F32[1], false};
+ return InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None};
case AttributeType::UnsignedInt:
- return AttrInfo{ctx.input_u32, ctx.U32[1], true};
+ return InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::Bitcast};
case AttributeType::SignedInt:
- return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true};
+ return InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true),
+ InputGenericLoadOp::Bitcast};
+ case AttributeType::SignedScaled:
+ return ctx.profile.support_scaled_attributes
+ ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None}
+ : InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true),
+ InputGenericLoadOp::SToF};
+ case AttributeType::UnsignedScaled:
+ return ctx.profile.support_scaled_attributes
+ ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None}
+ : InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::UToF};
case AttributeType::Disabled:
- return std::nullopt;
+ return InputGenericInfo{};
}
throw InvalidArgument("Invalid attribute type {}", type);
}
@@ -746,18 +754,29 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
continue;
}
AddLabel(labels[label_index]);
- const auto type{AttrTypes(*this, static_cast<u32>(index))};
- if (!type) {
+ const auto& generic{input_generics.at(index)};
+ const Id generic_id{generic.id};
+ if (!ValidId(generic_id)) {
OpReturnValue(Const(0.0f));
++label_index;
continue;
}
- const Id generic_id{input_generics.at(index)};
- const Id pointer{is_array
- ? OpAccessChain(type->pointer, generic_id, vertex, masked_index)
- : OpAccessChain(type->pointer, generic_id, masked_index)};
- const Id value{OpLoad(type->id, pointer)};
- const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value};
+ const Id pointer{
+ is_array ? OpAccessChain(generic.pointer_type, generic_id, vertex, masked_index)
+ : OpAccessChain(generic.pointer_type, generic_id, masked_index)};
+ const Id value{OpLoad(generic.component_type, pointer)};
+ const Id result{[this, generic, value]() {
+ switch (generic.load_op) {
+ case InputGenericLoadOp::Bitcast:
+ return OpBitcast(F32[1], value);
+ case InputGenericLoadOp::SToF:
+ return OpConvertSToF(F32[1], value);
+ case InputGenericLoadOp::UToF:
+ return OpConvertUToF(F32[1], value);
+ default:
+ return value;
+ };
+ }()};
OpReturnValue(result);
++label_index;
}
@@ -1457,7 +1476,7 @@ void EmitContext::DefineInputs(const IR::Program& program) {
const Id id{DefineInput(*this, type, true)};
Decorate(id, spv::Decoration::Location, static_cast<u32>(index));
Name(id, fmt::format("in_attr{}", index));
- input_generics[index] = id;
+ input_generics[index] = GetAttributeInfo(*this, input_type, id);
if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) {
Decorate(id, spv::Decoration::PassthroughNV);
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index 768a4fbb5..e63330f11 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -95,6 +95,20 @@ struct StorageDefinitions {
Id U32x4{};
};
+enum class InputGenericLoadOp {
+ None,
+ Bitcast,
+ SToF,
+ UToF,
+};
+
+struct InputGenericInfo {
+ Id id;
+ Id pointer_type;
+ Id component_type;
+ InputGenericLoadOp load_op;
+};
+
struct GenericElementInfo {
Id id{};
u32 first_element{};
@@ -283,7 +297,7 @@ public:
bool need_input_position_indirect{};
Id input_position{};
- std::array<Id, 32> input_generics{};
+ std::array<InputGenericInfo, 32> input_generics{};
Id output_point_size{};
Id output_position{};
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h
index 9f88fb440..9ca97f6a4 100644
--- a/src/shader_recompiler/profile.h
+++ b/src/shader_recompiler/profile.h
@@ -43,6 +43,7 @@ struct Profile {
bool support_gl_variable_aoffi{};
bool support_gl_sparse_textures{};
bool support_gl_derivative_control{};
+ bool support_scaled_attributes{};
bool warp_size_potentially_larger_than_guest{};
@@ -77,6 +78,8 @@ struct Profile {
bool has_gl_bool_ref_bug{};
/// Ignores SPIR-V ordered vs unordered using GLSL semantics
bool ignore_nan_fp_comparisons{};
+ /// Some drivers have broken support for OpVectorExtractDynamic on subgroup mask inputs
+ bool has_broken_spirv_subgroup_mask_vector_extract_dynamic{};
u32 gl_max_compute_smem_size{};
};
diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h
index 549b81ef7..3b63c249f 100644
--- a/src/shader_recompiler/runtime_info.h
+++ b/src/shader_recompiler/runtime_info.h
@@ -17,6 +17,8 @@ enum class AttributeType : u8 {
Float,
SignedInt,
UnsignedInt,
+ SignedScaled,
+ UnsignedScaled,
Disabled,
};