diff options
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 44 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | 61 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/spirv_emit_context.h | 16 | ||||
| -rw-r--r-- | src/shader_recompiler/profile.h | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/runtime_info.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/maxwell_to_vk.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 5 |
9 files changed, 97 insertions, 51 deletions
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 @@ | |||
| 10 | 10 | ||
| 11 | namespace Shader::Backend::SPIRV { | 11 | namespace Shader::Backend::SPIRV { |
| 12 | namespace { | 12 | namespace { |
| 13 | struct AttrInfo { | ||
| 14 | Id pointer; | ||
| 15 | Id id; | ||
| 16 | bool needs_cast; | ||
| 17 | }; | ||
| 18 | |||
| 19 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { | ||
| 20 | const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; | ||
| 21 | switch (type) { | ||
| 22 | case AttributeType::Float: | ||
| 23 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; | ||
| 24 | case AttributeType::UnsignedInt: | ||
| 25 | return AttrInfo{ctx.input_u32, ctx.U32[1], true}; | ||
| 26 | case AttributeType::SignedInt: | ||
| 27 | return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true}; | ||
| 28 | case AttributeType::Disabled: | ||
| 29 | return std::nullopt; | ||
| 30 | } | ||
| 31 | throw InvalidArgument("Invalid attribute type {}", type); | ||
| 32 | } | ||
| 33 | |||
| 34 | template <typename... Args> | 13 | template <typename... Args> |
| 35 | Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&... args) { | 14 | Id AttrPointer(EmitContext& ctx, Id pointer_type, Id vertex, Id base, Args&&... args) { |
| 36 | switch (ctx.stage) { | 15 | switch (ctx.stage) { |
| @@ -302,15 +281,26 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | |||
| 302 | const u32 element{static_cast<u32>(attr) % 4}; | 281 | const u32 element{static_cast<u32>(attr) % 4}; |
| 303 | if (IR::IsGeneric(attr)) { | 282 | if (IR::IsGeneric(attr)) { |
| 304 | const u32 index{IR::GenericAttributeIndex(attr)}; | 283 | const u32 index{IR::GenericAttributeIndex(attr)}; |
| 305 | const std::optional<AttrInfo> type{AttrTypes(ctx, index)}; | 284 | const auto& generic{ctx.input_generics.at(index)}; |
| 306 | if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index, element)) { | 285 | if (!ValidId(generic.id)) { |
| 307 | // Attribute is disabled or varying component is not written | 286 | // Attribute is disabled or varying component is not written |
| 308 | return ctx.Const(element == 3 ? 1.0f : 0.0f); | 287 | return ctx.Const(element == 3 ? 1.0f : 0.0f); |
| 309 | } | 288 | } |
| 310 | const Id generic_id{ctx.input_generics.at(index)}; | 289 | const Id pointer{ |
| 311 | const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))}; | 290 | AttrPointer(ctx, generic.pointer_type, vertex, generic.id, ctx.Const(element))}; |
| 312 | const Id value{ctx.OpLoad(type->id, pointer)}; | 291 | const Id value{ctx.OpLoad(generic.component_type, pointer)}; |
| 313 | return type->needs_cast ? ctx.OpBitcast(ctx.F32[1], value) : value; | 292 | return [&ctx, generic, value]() { |
| 293 | switch (generic.load_op) { | ||
| 294 | case InputGenericLoadOp::Bitcast: | ||
| 295 | return ctx.OpBitcast(ctx.F32[1], value); | ||
| 296 | case InputGenericLoadOp::SToF: | ||
| 297 | return ctx.OpConvertSToF(ctx.F32[1], value); | ||
| 298 | case InputGenericLoadOp::UToF: | ||
| 299 | return ctx.OpConvertUToF(ctx.F32[1], value); | ||
| 300 | default: | ||
| 301 | return value; | ||
| 302 | }; | ||
| 303 | }(); | ||
| 314 | } | 304 | } |
| 315 | switch (attr) { | 305 | switch (attr) { |
| 316 | case IR::Attribute::PrimitiveId: | 306 | case IR::Attribute::PrimitiveId: |
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 { | |||
| 25 | FPMax, | 25 | FPMax, |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | struct AttrInfo { | ||
| 29 | Id pointer; | ||
| 30 | Id id; | ||
| 31 | bool needs_cast; | ||
| 32 | }; | ||
| 33 | |||
| 34 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { | 28 | Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { |
| 35 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; | 29 | const spv::ImageFormat format{spv::ImageFormat::Unknown}; |
| 36 | const Id type{ctx.F32[1]}; | 30 | const Id type{ctx.F32[1]}; |
| @@ -206,23 +200,37 @@ Id GetAttributeType(EmitContext& ctx, AttributeType type) { | |||
| 206 | return ctx.TypeVector(ctx.TypeInt(32, true), 4); | 200 | return ctx.TypeVector(ctx.TypeInt(32, true), 4); |
| 207 | case AttributeType::UnsignedInt: | 201 | case AttributeType::UnsignedInt: |
| 208 | return ctx.U32[4]; | 202 | return ctx.U32[4]; |
| 203 | case AttributeType::SignedScaled: | ||
| 204 | return ctx.profile.support_scaled_attributes ? ctx.F32[4] | ||
| 205 | : ctx.TypeVector(ctx.TypeInt(32, true), 4); | ||
| 206 | case AttributeType::UnsignedScaled: | ||
| 207 | return ctx.profile.support_scaled_attributes ? ctx.F32[4] : ctx.U32[4]; | ||
| 209 | case AttributeType::Disabled: | 208 | case AttributeType::Disabled: |
| 210 | break; | 209 | break; |
| 211 | } | 210 | } |
| 212 | throw InvalidArgument("Invalid attribute type {}", type); | 211 | throw InvalidArgument("Invalid attribute type {}", type); |
| 213 | } | 212 | } |
| 214 | 213 | ||
| 215 | std::optional<AttrInfo> AttrTypes(EmitContext& ctx, u32 index) { | 214 | InputGenericInfo GetAttributeInfo(EmitContext& ctx, AttributeType type, Id id) { |
| 216 | const AttributeType type{ctx.runtime_info.generic_input_types.at(index)}; | ||
| 217 | switch (type) { | 215 | switch (type) { |
| 218 | case AttributeType::Float: | 216 | case AttributeType::Float: |
| 219 | return AttrInfo{ctx.input_f32, ctx.F32[1], false}; | 217 | return InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None}; |
| 220 | case AttributeType::UnsignedInt: | 218 | case AttributeType::UnsignedInt: |
| 221 | return AttrInfo{ctx.input_u32, ctx.U32[1], true}; | 219 | return InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::Bitcast}; |
| 222 | case AttributeType::SignedInt: | 220 | case AttributeType::SignedInt: |
| 223 | return AttrInfo{ctx.input_s32, ctx.TypeInt(32, true), true}; | 221 | return InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), |
| 222 | InputGenericLoadOp::Bitcast}; | ||
| 223 | case AttributeType::SignedScaled: | ||
| 224 | return ctx.profile.support_scaled_attributes | ||
| 225 | ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} | ||
| 226 | : InputGenericInfo{id, ctx.input_s32, ctx.TypeInt(32, true), | ||
| 227 | InputGenericLoadOp::SToF}; | ||
| 228 | case AttributeType::UnsignedScaled: | ||
| 229 | return ctx.profile.support_scaled_attributes | ||
| 230 | ? InputGenericInfo{id, ctx.input_f32, ctx.F32[1], InputGenericLoadOp::None} | ||
| 231 | : InputGenericInfo{id, ctx.input_u32, ctx.U32[1], InputGenericLoadOp::UToF}; | ||
| 224 | case AttributeType::Disabled: | 232 | case AttributeType::Disabled: |
| 225 | return std::nullopt; | 233 | return InputGenericInfo{}; |
| 226 | } | 234 | } |
| 227 | throw InvalidArgument("Invalid attribute type {}", type); | 235 | throw InvalidArgument("Invalid attribute type {}", type); |
| 228 | } | 236 | } |
| @@ -746,18 +754,29 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 746 | continue; | 754 | continue; |
| 747 | } | 755 | } |
| 748 | AddLabel(labels[label_index]); | 756 | AddLabel(labels[label_index]); |
| 749 | const auto type{AttrTypes(*this, static_cast<u32>(index))}; | 757 | const auto& generic{input_generics.at(index)}; |
| 750 | if (!type) { | 758 | const Id generic_id{generic.id}; |
| 759 | if (!ValidId(generic_id)) { | ||
| 751 | OpReturnValue(Const(0.0f)); | 760 | OpReturnValue(Const(0.0f)); |
| 752 | ++label_index; | 761 | ++label_index; |
| 753 | continue; | 762 | continue; |
| 754 | } | 763 | } |
| 755 | const Id generic_id{input_generics.at(index)}; | 764 | const Id pointer{ |
| 756 | const Id pointer{is_array | 765 | is_array ? OpAccessChain(generic.pointer_type, generic_id, vertex, masked_index) |
| 757 | ? OpAccessChain(type->pointer, generic_id, vertex, masked_index) | 766 | : OpAccessChain(generic.pointer_type, generic_id, masked_index)}; |
| 758 | : OpAccessChain(type->pointer, generic_id, masked_index)}; | 767 | const Id value{OpLoad(generic.component_type, pointer)}; |
| 759 | const Id value{OpLoad(type->id, pointer)}; | 768 | const Id result{[this, generic, value]() { |
| 760 | const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; | 769 | switch (generic.load_op) { |
| 770 | case InputGenericLoadOp::Bitcast: | ||
| 771 | return OpBitcast(F32[1], value); | ||
| 772 | case InputGenericLoadOp::SToF: | ||
| 773 | return OpConvertSToF(F32[1], value); | ||
| 774 | case InputGenericLoadOp::UToF: | ||
| 775 | return OpConvertUToF(F32[1], value); | ||
| 776 | default: | ||
| 777 | return value; | ||
| 778 | }; | ||
| 779 | }()}; | ||
| 761 | OpReturnValue(result); | 780 | OpReturnValue(result); |
| 762 | ++label_index; | 781 | ++label_index; |
| 763 | } | 782 | } |
| @@ -1457,7 +1476,7 @@ void EmitContext::DefineInputs(const IR::Program& program) { | |||
| 1457 | const Id id{DefineInput(*this, type, true)}; | 1476 | const Id id{DefineInput(*this, type, true)}; |
| 1458 | Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); | 1477 | Decorate(id, spv::Decoration::Location, static_cast<u32>(index)); |
| 1459 | Name(id, fmt::format("in_attr{}", index)); | 1478 | Name(id, fmt::format("in_attr{}", index)); |
| 1460 | input_generics[index] = id; | 1479 | input_generics[index] = GetAttributeInfo(*this, input_type, id); |
| 1461 | 1480 | ||
| 1462 | if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) { | 1481 | if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) { |
| 1463 | Decorate(id, spv::Decoration::PassthroughNV); | 1482 | 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 { | |||
| 95 | Id U32x4{}; | 95 | Id U32x4{}; |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | enum class InputGenericLoadOp { | ||
| 99 | None, | ||
| 100 | Bitcast, | ||
| 101 | SToF, | ||
| 102 | UToF, | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct InputGenericInfo { | ||
| 106 | Id id; | ||
| 107 | Id pointer_type; | ||
| 108 | Id component_type; | ||
| 109 | InputGenericLoadOp load_op; | ||
| 110 | }; | ||
| 111 | |||
| 98 | struct GenericElementInfo { | 112 | struct GenericElementInfo { |
| 99 | Id id{}; | 113 | Id id{}; |
| 100 | u32 first_element{}; | 114 | u32 first_element{}; |
| @@ -283,7 +297,7 @@ public: | |||
| 283 | 297 | ||
| 284 | bool need_input_position_indirect{}; | 298 | bool need_input_position_indirect{}; |
| 285 | Id input_position{}; | 299 | Id input_position{}; |
| 286 | std::array<Id, 32> input_generics{}; | 300 | std::array<InputGenericInfo, 32> input_generics{}; |
| 287 | 301 | ||
| 288 | Id output_point_size{}; | 302 | Id output_point_size{}; |
| 289 | Id output_position{}; | 303 | Id output_position{}; |
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 9f88fb440..3bb4a7e6f 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h | |||
| @@ -43,6 +43,7 @@ struct Profile { | |||
| 43 | bool support_gl_variable_aoffi{}; | 43 | bool support_gl_variable_aoffi{}; |
| 44 | bool support_gl_sparse_textures{}; | 44 | bool support_gl_sparse_textures{}; |
| 45 | bool support_gl_derivative_control{}; | 45 | bool support_gl_derivative_control{}; |
| 46 | bool support_scaled_attributes{}; | ||
| 46 | 47 | ||
| 47 | bool warp_size_potentially_larger_than_guest{}; | 48 | bool warp_size_potentially_larger_than_guest{}; |
| 48 | 49 | ||
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 { | |||
| 17 | Float, | 17 | Float, |
| 18 | SignedInt, | 18 | SignedInt, |
| 19 | UnsignedInt, | 19 | UnsignedInt, |
| 20 | SignedScaled, | ||
| 21 | UnsignedScaled, | ||
| 20 | Disabled, | 22 | Disabled, |
| 21 | }; | 23 | }; |
| 22 | 24 | ||
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index b75d7220d..9a0b10568 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -347,6 +347,14 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const Device& device, | |||
| 347 | 347 | ||
| 348 | VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, | 348 | VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, |
| 349 | Maxwell::VertexAttribute::Size size) { | 349 | Maxwell::VertexAttribute::Size size) { |
| 350 | if (device.MustEmulateScaledFormats()) { | ||
| 351 | if (type == Maxwell::VertexAttribute::Type::SScaled) { | ||
| 352 | type = Maxwell::VertexAttribute::Type::SInt; | ||
| 353 | } else if (type == Maxwell::VertexAttribute::Type::UScaled) { | ||
| 354 | type = Maxwell::VertexAttribute::Type::UInt; | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 350 | const VkFormat format{([&]() { | 358 | const VkFormat format{([&]() { |
| 351 | switch (type) { | 359 | switch (type) { |
| 352 | case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway: | 360 | case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway: |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ec55e11b1..e39713761 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -114,14 +114,16 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut | |||
| 114 | return Shader::AttributeType::Disabled; | 114 | return Shader::AttributeType::Disabled; |
| 115 | case Maxwell::VertexAttribute::Type::SNorm: | 115 | case Maxwell::VertexAttribute::Type::SNorm: |
| 116 | case Maxwell::VertexAttribute::Type::UNorm: | 116 | case Maxwell::VertexAttribute::Type::UNorm: |
| 117 | case Maxwell::VertexAttribute::Type::UScaled: | ||
| 118 | case Maxwell::VertexAttribute::Type::SScaled: | ||
| 119 | case Maxwell::VertexAttribute::Type::Float: | 117 | case Maxwell::VertexAttribute::Type::Float: |
| 120 | return Shader::AttributeType::Float; | 118 | return Shader::AttributeType::Float; |
| 121 | case Maxwell::VertexAttribute::Type::SInt: | 119 | case Maxwell::VertexAttribute::Type::SInt: |
| 122 | return Shader::AttributeType::SignedInt; | 120 | return Shader::AttributeType::SignedInt; |
| 123 | case Maxwell::VertexAttribute::Type::UInt: | 121 | case Maxwell::VertexAttribute::Type::UInt: |
| 124 | return Shader::AttributeType::UnsignedInt; | 122 | return Shader::AttributeType::UnsignedInt; |
| 123 | case Maxwell::VertexAttribute::Type::UScaled: | ||
| 124 | return Shader::AttributeType::UnsignedScaled; | ||
| 125 | case Maxwell::VertexAttribute::Type::SScaled: | ||
| 126 | return Shader::AttributeType::SignedScaled; | ||
| 125 | } | 127 | } |
| 126 | return Shader::AttributeType::Float; | 128 | return Shader::AttributeType::Float; |
| 127 | } | 129 | } |
| @@ -331,6 +333,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 331 | .support_derivative_control = true, | 333 | .support_derivative_control = true, |
| 332 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), | 334 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), |
| 333 | .support_native_ndc = device.IsExtDepthClipControlSupported(), | 335 | .support_native_ndc = device.IsExtDepthClipControlSupported(), |
| 336 | .support_scaled_attributes = !device.MustEmulateScaledFormats(), | ||
| 334 | 337 | ||
| 335 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | 338 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), |
| 336 | 339 | ||
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 01540c10b..63e1c7d63 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -363,6 +363,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 363 | 363 | ||
| 364 | #ifdef ANDROID | 364 | #ifdef ANDROID |
| 365 | if (is_adreno) { | 365 | if (is_adreno) { |
| 366 | must_emulate_scaled_formats = true; | ||
| 367 | |||
| 366 | LOG_WARNING(Render_Vulkan, "Adreno drivers have broken VK_EXT_extended_dynamic_state"); | 368 | LOG_WARNING(Render_Vulkan, "Adreno drivers have broken VK_EXT_extended_dynamic_state"); |
| 367 | extensions.extended_dynamic_state = false; | 369 | extensions.extended_dynamic_state = false; |
| 368 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 370 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| @@ -391,6 +393,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 391 | } | 393 | } |
| 392 | 394 | ||
| 393 | if (is_arm) { | 395 | if (is_arm) { |
| 396 | must_emulate_scaled_formats = true; | ||
| 397 | |||
| 394 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); | 398 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); |
| 395 | extensions.extended_dynamic_state = false; | 399 | extensions.extended_dynamic_state = false; |
| 396 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 400 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5f1c63ff9..f9d8c47ba 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -551,6 +551,10 @@ public: | |||
| 551 | return cant_blit_msaa; | 551 | return cant_blit_msaa; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | bool MustEmulateScaledFormats() const { | ||
| 555 | return must_emulate_scaled_formats; | ||
| 556 | } | ||
| 557 | |||
| 554 | bool MustEmulateBGR565() const { | 558 | bool MustEmulateBGR565() const { |
| 555 | return must_emulate_bgr565; | 559 | return must_emulate_bgr565; |
| 556 | } | 560 | } |
| @@ -666,6 +670,7 @@ private: | |||
| 666 | bool has_nsight_graphics{}; ///< Has Nsight Graphics attached | 670 | bool has_nsight_graphics{}; ///< Has Nsight Graphics attached |
| 667 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. | 671 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. |
| 668 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. | 672 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. |
| 673 | bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation | ||
| 669 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. | 674 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. |
| 670 | bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. | 675 | bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. |
| 671 | bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. | 676 | bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. |