diff options
| -rw-r--r-- | src/input_common/mouse/mouse_input.cpp | 26 | ||||
| -rw-r--r-- | src/input_common/sdl/sdl_impl.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | 83 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/fixed_pipeline_state.h | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.cpp | 34 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.h | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 9 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_filesystem.cpp | 10 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_filesystem.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_filesystem.ui | 35 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 3 |
14 files changed, 131 insertions, 118 deletions
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index 67a584d53..b864d26f2 100644 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp | |||
| @@ -33,11 +33,16 @@ void Mouse::UpdateThread() { | |||
| 33 | info.motion.UpdateOrientation(update_time * 1000); | 33 | info.motion.UpdateOrientation(update_time * 1000); |
| 34 | info.tilt_speed = 0; | 34 | info.tilt_speed = 0; |
| 35 | info.data.motion = info.motion.GetMotion(); | 35 | info.data.motion = info.motion.GetMotion(); |
| 36 | if (Settings::values.mouse_panning) { | ||
| 37 | info.last_mouse_change *= 0.96f; | ||
| 38 | info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x), | ||
| 39 | static_cast<int>(16 * -info.last_mouse_change.y)}; | ||
| 40 | } | ||
| 36 | } | 41 | } |
| 37 | if (configuring) { | 42 | if (configuring) { |
| 38 | UpdateYuzuSettings(); | 43 | UpdateYuzuSettings(); |
| 39 | } | 44 | } |
| 40 | if (mouse_panning_timout++ > 8) { | 45 | if (mouse_panning_timout++ > 20) { |
| 41 | StopPanning(); | 46 | StopPanning(); |
| 42 | } | 47 | } |
| 43 | std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); | 48 | std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); |
| @@ -82,16 +87,27 @@ void Mouse::StopPanning() { | |||
| 82 | void Mouse::MouseMove(int x, int y, int center_x, int center_y) { | 87 | void Mouse::MouseMove(int x, int y, int center_x, int center_y) { |
| 83 | for (MouseInfo& info : mouse_info) { | 88 | for (MouseInfo& info : mouse_info) { |
| 84 | if (Settings::values.mouse_panning) { | 89 | if (Settings::values.mouse_panning) { |
| 85 | const auto mouse_change = Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y); | 90 | auto mouse_change = |
| 91 | (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); | ||
| 86 | mouse_panning_timout = 0; | 92 | mouse_panning_timout = 0; |
| 87 | 93 | ||
| 88 | if (mouse_change.y == 0 && mouse_change.x == 0) { | 94 | if (mouse_change.y == 0 && mouse_change.x == 0) { |
| 89 | continue; | 95 | continue; |
| 90 | } | 96 | } |
| 97 | const auto mouse_change_length = mouse_change.Length(); | ||
| 98 | if (mouse_change_length < 3.0f) { | ||
| 99 | mouse_change /= mouse_change_length / 3.0f; | ||
| 100 | } | ||
| 101 | |||
| 102 | info.last_mouse_change = (info.last_mouse_change * 0.91f) + (mouse_change * 0.09f); | ||
| 103 | |||
| 104 | const auto last_mouse_change_length = info.last_mouse_change.Length(); | ||
| 105 | if (last_mouse_change_length > 8.0f) { | ||
| 106 | info.last_mouse_change /= last_mouse_change_length / 8.0f; | ||
| 107 | } else if (last_mouse_change_length < 1.0f) { | ||
| 108 | info.last_mouse_change = mouse_change / mouse_change.Length(); | ||
| 109 | } | ||
| 91 | 110 | ||
| 92 | info.last_mouse_change = (info.last_mouse_change * 0.8f) + (mouse_change * 0.2f); | ||
| 93 | info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x), | ||
| 94 | static_cast<int>(16 * -info.last_mouse_change.y)}; | ||
| 95 | info.tilt_direction = info.last_mouse_change; | 111 | info.tilt_direction = info.last_mouse_change; |
| 96 | info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity; | 112 | info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity; |
| 97 | continue; | 113 | continue; |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index f67de37e3..a88ae452f 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -717,6 +717,13 @@ SDLState::SDLState() { | |||
| 717 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { | 717 | if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { |
| 718 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); | 718 | LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError()); |
| 719 | } | 719 | } |
| 720 | // these hints are only defined on sdl2.0.9 or higher | ||
| 721 | #if SDL_VERSION_ATLEAST(2, 0, 9) | ||
| 722 | #if !SDL_VERSION_ATLEAST(2, 0, 12) | ||
| 723 | // There are also hints to toggle the individual drivers if needed. | ||
| 724 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI, "0"); | ||
| 725 | #endif | ||
| 726 | #endif | ||
| 720 | 727 | ||
| 721 | SDL_AddEventWatch(&SDLEventWatcher, this); | 728 | SDL_AddEventWatch(&SDLEventWatcher, this); |
| 722 | 729 | ||
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 5be6dabd9..362278f01 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -12,14 +12,15 @@ | |||
| 12 | #include "common/cityhash.h" | 12 | #include "common/cityhash.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 14 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 15 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | ||
| 15 | 16 | ||
| 16 | namespace Vulkan { | 17 | namespace Vulkan { |
| 17 | 18 | ||
| 18 | namespace { | 19 | namespace { |
| 19 | 20 | ||
| 20 | constexpr std::size_t POINT = 0; | 21 | constexpr size_t POINT = 0; |
| 21 | constexpr std::size_t LINE = 1; | 22 | constexpr size_t LINE = 1; |
| 22 | constexpr std::size_t POLYGON = 2; | 23 | constexpr size_t POLYGON = 2; |
| 23 | constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { | 24 | constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { |
| 24 | POINT, // Points | 25 | POINT, // Points |
| 25 | LINE, // Lines | 26 | LINE, // Lines |
| @@ -40,10 +41,14 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { | |||
| 40 | 41 | ||
| 41 | } // Anonymous namespace | 42 | } // Anonymous namespace |
| 42 | 43 | ||
| 43 | void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) { | 44 | void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, |
| 44 | const std::array enabled_lut = {regs.polygon_offset_point_enable, | 45 | bool has_extended_dynamic_state) { |
| 45 | regs.polygon_offset_line_enable, | 46 | const Maxwell& regs = maxwell3d.regs; |
| 46 | regs.polygon_offset_fill_enable}; | 47 | const std::array enabled_lut{ |
| 48 | regs.polygon_offset_point_enable, | ||
| 49 | regs.polygon_offset_line_enable, | ||
| 50 | regs.polygon_offset_fill_enable, | ||
| 51 | }; | ||
| 47 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); | 52 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); |
| 48 | 53 | ||
| 49 | raw1 = 0; | 54 | raw1 = 0; |
| @@ -64,45 +69,53 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta | |||
| 64 | 69 | ||
| 65 | raw2 = 0; | 70 | raw2 = 0; |
| 66 | const auto test_func = | 71 | const auto test_func = |
| 67 | regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; | 72 | regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; |
| 68 | alpha_test_func.Assign(PackComparisonOp(test_func)); | 73 | alpha_test_func.Assign(PackComparisonOp(test_func)); |
| 69 | early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0); | 74 | early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0); |
| 70 | 75 | ||
| 71 | alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); | 76 | alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); |
| 72 | point_size = Common::BitCast<u32>(regs.point_size); | 77 | point_size = Common::BitCast<u32>(regs.point_size); |
| 73 | 78 | ||
| 74 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 79 | if (maxwell3d.dirty.flags[Dirty::InstanceDivisors]) { |
| 75 | binding_divisors[index] = | 80 | maxwell3d.dirty.flags[Dirty::InstanceDivisors] = false; |
| 76 | regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0; | 81 | for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 82 | const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index); | ||
| 83 | binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0; | ||
| 84 | } | ||
| 77 | } | 85 | } |
| 78 | 86 | if (maxwell3d.dirty.flags[Dirty::VertexAttributes]) { | |
| 79 | for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { | 87 | maxwell3d.dirty.flags[Dirty::VertexAttributes] = false; |
| 80 | const auto& input = regs.vertex_attrib_format[index]; | 88 | for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
| 81 | auto& attribute = attributes[index]; | 89 | const auto& input = regs.vertex_attrib_format[index]; |
| 82 | attribute.raw = 0; | 90 | auto& attribute = attributes[index]; |
| 83 | attribute.enabled.Assign(input.IsConstant() ? 0 : 1); | 91 | attribute.raw = 0; |
| 84 | attribute.buffer.Assign(input.buffer); | 92 | attribute.enabled.Assign(input.IsConstant() ? 0 : 1); |
| 85 | attribute.offset.Assign(input.offset); | 93 | attribute.buffer.Assign(input.buffer); |
| 86 | attribute.type.Assign(static_cast<u32>(input.type.Value())); | 94 | attribute.offset.Assign(input.offset); |
| 87 | attribute.size.Assign(static_cast<u32>(input.size.Value())); | 95 | attribute.type.Assign(static_cast<u32>(input.type.Value())); |
| 88 | attribute.binding_index_enabled.Assign(regs.vertex_array[index].IsEnabled() ? 1 : 0); | 96 | attribute.size.Assign(static_cast<u32>(input.size.Value())); |
| 97 | } | ||
| 89 | } | 98 | } |
| 90 | 99 | if (maxwell3d.dirty.flags[Dirty::Blending]) { | |
| 91 | for (std::size_t index = 0; index < std::size(attachments); ++index) { | 100 | maxwell3d.dirty.flags[Dirty::Blending] = false; |
| 92 | attachments[index].Fill(regs, index); | 101 | for (size_t index = 0; index < attachments.size(); ++index) { |
| 102 | attachments[index].Refresh(regs, index); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | if (maxwell3d.dirty.flags[Dirty::ViewportSwizzles]) { | ||
| 106 | maxwell3d.dirty.flags[Dirty::ViewportSwizzles] = false; | ||
| 107 | const auto& transform = regs.viewport_transform; | ||
| 108 | std::ranges::transform(transform, viewport_swizzles.begin(), [](const auto& viewport) { | ||
| 109 | return static_cast<u16>(viewport.swizzle.raw); | ||
| 110 | }); | ||
| 93 | } | 111 | } |
| 94 | |||
| 95 | const auto& transform = regs.viewport_transform; | ||
| 96 | std::transform(transform.begin(), transform.end(), viewport_swizzles.begin(), | ||
| 97 | [](const auto& viewport) { return static_cast<u16>(viewport.swizzle.raw); }); | ||
| 98 | |||
| 99 | if (!has_extended_dynamic_state) { | 112 | if (!has_extended_dynamic_state) { |
| 100 | no_extended_dynamic_state.Assign(1); | 113 | no_extended_dynamic_state.Assign(1); |
| 101 | dynamic_state.Fill(regs); | 114 | dynamic_state.Refresh(regs); |
| 102 | } | 115 | } |
| 103 | } | 116 | } |
| 104 | 117 | ||
| 105 | void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) { | 118 | void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t index) { |
| 106 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; | 119 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; |
| 107 | 120 | ||
| 108 | raw = 0; | 121 | raw = 0; |
| @@ -141,7 +154,7 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size | |||
| 141 | enable.Assign(1); | 154 | enable.Assign(1); |
| 142 | } | 155 | } |
| 143 | 156 | ||
| 144 | void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { | 157 | void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) { |
| 145 | u32 packed_front_face = PackFrontFace(regs.front_face); | 158 | u32 packed_front_face = PackFrontFace(regs.front_face); |
| 146 | if (regs.screen_y_control.triangle_rast_flip != 0) { | 159 | if (regs.screen_y_control.triangle_rast_flip != 0) { |
| 147 | // Flip front face | 160 | // Flip front face |
| @@ -178,9 +191,9 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { | |||
| 178 | }); | 191 | }); |
| 179 | } | 192 | } |
| 180 | 193 | ||
| 181 | std::size_t FixedPipelineState::Hash() const noexcept { | 194 | size_t FixedPipelineState::Hash() const noexcept { |
| 182 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size()); | 195 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size()); |
| 183 | return static_cast<std::size_t>(hash); | 196 | return static_cast<size_t>(hash); |
| 184 | } | 197 | } |
| 185 | 198 | ||
| 186 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { | 199 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 465a55fdb..a0eb83a68 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -58,7 +58,7 @@ struct FixedPipelineState { | |||
| 58 | BitField<30, 1, u32> enable; | 58 | BitField<30, 1, u32> enable; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | void Fill(const Maxwell& regs, std::size_t index); | 61 | void Refresh(const Maxwell& regs, size_t index); |
| 62 | 62 | ||
| 63 | constexpr std::array<bool, 4> Mask() const noexcept { | 63 | constexpr std::array<bool, 4> Mask() const noexcept { |
| 64 | return {mask_r != 0, mask_g != 0, mask_b != 0, mask_a != 0}; | 64 | return {mask_r != 0, mask_g != 0, mask_b != 0, mask_a != 0}; |
| @@ -96,8 +96,6 @@ struct FixedPipelineState { | |||
| 96 | BitField<6, 14, u32> offset; | 96 | BitField<6, 14, u32> offset; |
| 97 | BitField<20, 3, u32> type; | 97 | BitField<20, 3, u32> type; |
| 98 | BitField<23, 6, u32> size; | 98 | BitField<23, 6, u32> size; |
| 99 | // Not really an element of a vertex attribute, but it can be packed here | ||
| 100 | BitField<29, 1, u32> binding_index_enabled; | ||
| 101 | 99 | ||
| 102 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { | 100 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { |
| 103 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); | 101 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); |
| @@ -108,7 +106,7 @@ struct FixedPipelineState { | |||
| 108 | } | 106 | } |
| 109 | }; | 107 | }; |
| 110 | 108 | ||
| 111 | template <std::size_t Position> | 109 | template <size_t Position> |
| 112 | union StencilFace { | 110 | union StencilFace { |
| 113 | BitField<Position + 0, 3, u32> action_stencil_fail; | 111 | BitField<Position + 0, 3, u32> action_stencil_fail; |
| 114 | BitField<Position + 3, 3, u32> action_depth_fail; | 112 | BitField<Position + 3, 3, u32> action_depth_fail; |
| @@ -152,7 +150,7 @@ struct FixedPipelineState { | |||
| 152 | // Vertex stride is a 12 bits value, we have 4 bits to spare per element | 150 | // Vertex stride is a 12 bits value, we have 4 bits to spare per element |
| 153 | std::array<u16, Maxwell::NumVertexArrays> vertex_strides; | 151 | std::array<u16, Maxwell::NumVertexArrays> vertex_strides; |
| 154 | 152 | ||
| 155 | void Fill(const Maxwell& regs); | 153 | void Refresh(const Maxwell& regs); |
| 156 | 154 | ||
| 157 | Maxwell::ComparisonOp DepthTestFunc() const noexcept { | 155 | Maxwell::ComparisonOp DepthTestFunc() const noexcept { |
| 158 | return UnpackComparisonOp(depth_test_func); | 156 | return UnpackComparisonOp(depth_test_func); |
| @@ -199,9 +197,9 @@ struct FixedPipelineState { | |||
| 199 | std::array<u16, Maxwell::NumViewports> viewport_swizzles; | 197 | std::array<u16, Maxwell::NumViewports> viewport_swizzles; |
| 200 | DynamicState dynamic_state; | 198 | DynamicState dynamic_state; |
| 201 | 199 | ||
| 202 | void Fill(const Maxwell& regs, bool has_extended_dynamic_state); | 200 | void Refresh(Tegra::Engines::Maxwell3D& maxwell3d, bool has_extended_dynamic_state); |
| 203 | 201 | ||
| 204 | std::size_t Hash() const noexcept; | 202 | size_t Hash() const noexcept; |
| 205 | 203 | ||
| 206 | bool operator==(const FixedPipelineState& rhs) const noexcept; | 204 | bool operator==(const FixedPipelineState& rhs) const noexcept; |
| 207 | 205 | ||
| @@ -209,8 +207,8 @@ struct FixedPipelineState { | |||
| 209 | return !operator==(rhs); | 207 | return !operator==(rhs); |
| 210 | } | 208 | } |
| 211 | 209 | ||
| 212 | std::size_t Size() const noexcept { | 210 | size_t Size() const noexcept { |
| 213 | const std::size_t total_size = sizeof *this; | 211 | const size_t total_size = sizeof *this; |
| 214 | return total_size - (no_extended_dynamic_state != 0 ? 0 : sizeof(DynamicState)); | 212 | return total_size - (no_extended_dynamic_state != 0 ? 0 : sizeof(DynamicState)); |
| 215 | } | 213 | } |
| 216 | }; | 214 | }; |
| @@ -224,7 +222,7 @@ namespace std { | |||
| 224 | 222 | ||
| 225 | template <> | 223 | template <> |
| 226 | struct hash<Vulkan::FixedPipelineState> { | 224 | struct hash<Vulkan::FixedPipelineState> { |
| 227 | std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { | 225 | size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { |
| 228 | return k.Hash(); | 226 | return k.Hash(); |
| 229 | } | 227 | } |
| 230 | }; | 228 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index d50dca604..fc6dd83eb 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -221,9 +221,6 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const SPIRVProgram& program, | |||
| 221 | std::vector<VkVertexInputBindingDescription> vertex_bindings; | 221 | std::vector<VkVertexInputBindingDescription> vertex_bindings; |
| 222 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; | 222 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; |
| 223 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 223 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 224 | if (state.attributes[index].binding_index_enabled == 0) { | ||
| 225 | continue; | ||
| 226 | } | ||
| 227 | const bool instanced = state.binding_divisors[index] != 0; | 224 | const bool instanced = state.binding_divisors[index] != 0; |
| 228 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; | 225 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; |
| 229 | vertex_bindings.push_back({ | 226 | vertex_bindings.push_back({ |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 684d4e3a6..dfd38f575 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -267,8 +267,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 267 | 267 | ||
| 268 | query_cache.UpdateCounters(); | 268 | query_cache.UpdateCounters(); |
| 269 | 269 | ||
| 270 | GraphicsPipelineCacheKey key; | 270 | graphics_key.fixed_state.Refresh(maxwell3d, device.IsExtExtendedDynamicStateSupported()); |
| 271 | key.fixed_state.Fill(maxwell3d.regs, device.IsExtExtendedDynamicStateSupported()); | ||
| 272 | 271 | ||
| 273 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | 272 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; |
| 274 | 273 | ||
| @@ -276,14 +275,15 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 276 | texture_cache.UpdateRenderTargets(false); | 275 | texture_cache.UpdateRenderTargets(false); |
| 277 | 276 | ||
| 278 | const auto shaders = pipeline_cache.GetShaders(); | 277 | const auto shaders = pipeline_cache.GetShaders(); |
| 279 | key.shaders = GetShaderAddresses(shaders); | 278 | graphics_key.shaders = GetShaderAddresses(shaders); |
| 279 | |||
| 280 | SetupShaderDescriptors(shaders, is_indexed); | 280 | SetupShaderDescriptors(shaders, is_indexed); |
| 281 | 281 | ||
| 282 | const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); | 282 | const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); |
| 283 | key.renderpass = framebuffer->RenderPass(); | 283 | graphics_key.renderpass = framebuffer->RenderPass(); |
| 284 | 284 | ||
| 285 | auto* const pipeline = | 285 | VKGraphicsPipeline* const pipeline = pipeline_cache.GetGraphicsPipeline( |
| 286 | pipeline_cache.GetGraphicsPipeline(key, framebuffer->NumColorBuffers(), async_shaders); | 286 | graphics_key, framebuffer->NumColorBuffers(), async_shaders); |
| 287 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { | 287 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { |
| 288 | // Async graphics pipeline was not ready. | 288 | // Async graphics pipeline was not ready. |
| 289 | return; | 289 | return; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 7fc6741da..acea1ba2d 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 20 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 21 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 21 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 22 | #include "video_core/renderer_vulkan/vk_fence_manager.h" | 22 | #include "video_core/renderer_vulkan/vk_fence_manager.h" |
| 23 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" | ||
| 23 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 24 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 24 | #include "video_core/renderer_vulkan/vk_query_cache.h" | 25 | #include "video_core/renderer_vulkan/vk_query_cache.h" |
| 25 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 26 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| @@ -173,6 +174,8 @@ private: | |||
| 173 | VKUpdateDescriptorQueue update_descriptor_queue; | 174 | VKUpdateDescriptorQueue update_descriptor_queue; |
| 174 | BlitImageHelper blit_image; | 175 | BlitImageHelper blit_image; |
| 175 | 176 | ||
| 177 | GraphicsPipelineCacheKey graphics_key; | ||
| 178 | |||
| 176 | TextureCacheRuntime texture_cache_runtime; | 179 | TextureCacheRuntime texture_cache_runtime; |
| 177 | TextureCache texture_cache; | 180 | TextureCache texture_cache; |
| 178 | BufferCacheRuntime buffer_cache_runtime; | 181 | BufferCacheRuntime buffer_cache_runtime; |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index e81fad007..956f86845 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -18,9 +18,7 @@ | |||
| 18 | #define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32))) | 18 | #define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32))) |
| 19 | 19 | ||
| 20 | namespace Vulkan { | 20 | namespace Vulkan { |
| 21 | |||
| 22 | namespace { | 21 | namespace { |
| 23 | |||
| 24 | using namespace Dirty; | 22 | using namespace Dirty; |
| 25 | using namespace VideoCommon::Dirty; | 23 | using namespace VideoCommon::Dirty; |
| 26 | using Tegra::Engines::Maxwell3D; | 24 | using Tegra::Engines::Maxwell3D; |
| @@ -128,6 +126,34 @@ void SetupDirtyStencilTestEnable(Tables& tables) { | |||
| 128 | tables[0][OFF(stencil_enable)] = StencilTestEnable; | 126 | tables[0][OFF(stencil_enable)] = StencilTestEnable; |
| 129 | } | 127 | } |
| 130 | 128 | ||
| 129 | void SetupDirtyBlending(Tables& tables) { | ||
| 130 | tables[0][OFF(color_mask_common)] = Blending; | ||
| 131 | tables[0][OFF(independent_blend_enable)] = Blending; | ||
| 132 | FillBlock(tables[0], OFF(color_mask), NUM(color_mask), Blending); | ||
| 133 | FillBlock(tables[0], OFF(blend), NUM(blend), Blending); | ||
| 134 | FillBlock(tables[0], OFF(independent_blend), NUM(independent_blend), Blending); | ||
| 135 | } | ||
| 136 | |||
| 137 | void SetupDirtyInstanceDivisors(Tables& tables) { | ||
| 138 | static constexpr size_t divisor_offset = 3; | ||
| 139 | for (size_t index = 0; index < Regs::NumVertexArrays; ++index) { | ||
| 140 | tables[0][OFF(instanced_arrays) + index] = InstanceDivisors; | ||
| 141 | tables[0][OFF(vertex_array) + index * NUM(vertex_array[0]) + divisor_offset] = | ||
| 142 | InstanceDivisors; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void SetupDirtyVertexAttributes(Tables& tables) { | ||
| 147 | FillBlock(tables[0], OFF(vertex_attrib_format), NUM(vertex_attrib_format), VertexAttributes); | ||
| 148 | } | ||
| 149 | |||
| 150 | void SetupDirtyViewportSwizzles(Tables& tables) { | ||
| 151 | static constexpr size_t swizzle_offset = 6; | ||
| 152 | for (size_t index = 0; index < Regs::NumViewports; ++index) { | ||
| 153 | tables[0][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] = | ||
| 154 | ViewportSwizzles; | ||
| 155 | } | ||
| 156 | } | ||
| 131 | } // Anonymous namespace | 157 | } // Anonymous namespace |
| 132 | 158 | ||
| 133 | StateTracker::StateTracker(Tegra::GPU& gpu) | 159 | StateTracker::StateTracker(Tegra::GPU& gpu) |
| @@ -148,6 +174,10 @@ StateTracker::StateTracker(Tegra::GPU& gpu) | |||
| 148 | SetupDirtyFrontFace(tables); | 174 | SetupDirtyFrontFace(tables); |
| 149 | SetupDirtyStencilOp(tables); | 175 | SetupDirtyStencilOp(tables); |
| 150 | SetupDirtyStencilTestEnable(tables); | 176 | SetupDirtyStencilTestEnable(tables); |
| 177 | SetupDirtyBlending(tables); | ||
| 178 | SetupDirtyInstanceDivisors(tables); | ||
| 179 | SetupDirtyVertexAttributes(tables); | ||
| 180 | SetupDirtyViewportSwizzles(tables); | ||
| 151 | } | 181 | } |
| 152 | 182 | ||
| 153 | } // namespace Vulkan | 183 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index c335d2bdf..84e918a71 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -35,6 +35,11 @@ enum : u8 { | |||
| 35 | StencilOp, | 35 | StencilOp, |
| 36 | StencilTestEnable, | 36 | StencilTestEnable, |
| 37 | 37 | ||
| 38 | Blending, | ||
| 39 | InstanceDivisors, | ||
| 40 | VertexAttributes, | ||
| 41 | ViewportSwizzles, | ||
| 42 | |||
| 38 | Last | 43 | Last |
| 39 | }; | 44 | }; |
| 40 | static_assert(Last <= std::numeric_limits<u8>::max()); | 45 | static_assert(Last <= std::numeric_limits<u8>::max()); |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 0635d13d0..3d6f64300 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -614,12 +614,6 @@ void Config::ReadDataStorageValues() { | |||
| 614 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))) | 614 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))) |
| 615 | .toString() | 615 | .toString() |
| 616 | .toStdString()); | 616 | .toStdString()); |
| 617 | FS::GetUserPath(FS::UserPath::CacheDir, | ||
| 618 | qt_config | ||
| 619 | ->value(QStringLiteral("cache_directory"), | ||
| 620 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir))) | ||
| 621 | .toString() | ||
| 622 | .toStdString()); | ||
| 623 | Settings::values.gamecard_inserted = | 617 | Settings::values.gamecard_inserted = |
| 624 | ReadSetting(QStringLiteral("gamecard_inserted"), false).toBool(); | 618 | ReadSetting(QStringLiteral("gamecard_inserted"), false).toBool(); |
| 625 | Settings::values.gamecard_current_game = | 619 | Settings::values.gamecard_current_game = |
| @@ -1218,9 +1212,6 @@ void Config::SaveDataStorageValues() { | |||
| 1218 | WriteSetting(QStringLiteral("dump_directory"), | 1212 | WriteSetting(QStringLiteral("dump_directory"), |
| 1219 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir)), | 1213 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir)), |
| 1220 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))); | 1214 | QString::fromStdString(FS::GetUserPath(FS::UserPath::DumpDir))); |
| 1221 | WriteSetting(QStringLiteral("cache_directory"), | ||
| 1222 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir)), | ||
| 1223 | QString::fromStdString(FS::GetUserPath(FS::UserPath::CacheDir))); | ||
| 1224 | WriteSetting(QStringLiteral("gamecard_inserted"), Settings::values.gamecard_inserted, false); | 1215 | WriteSetting(QStringLiteral("gamecard_inserted"), Settings::values.gamecard_inserted, false); |
| 1225 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, | 1216 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, |
| 1226 | false); | 1217 | false); |
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index 7ab4a80f7..bde2d4620 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp | |||
| @@ -26,8 +26,6 @@ ConfigureFilesystem::ConfigureFilesystem(QWidget* parent) | |||
| 26 | [this] { SetDirectory(DirectoryTarget::Dump, ui->dump_path_edit); }); | 26 | [this] { SetDirectory(DirectoryTarget::Dump, ui->dump_path_edit); }); |
| 27 | connect(ui->load_path_button, &QToolButton::pressed, this, | 27 | connect(ui->load_path_button, &QToolButton::pressed, this, |
| 28 | [this] { SetDirectory(DirectoryTarget::Load, ui->load_path_edit); }); | 28 | [this] { SetDirectory(DirectoryTarget::Load, ui->load_path_edit); }); |
| 29 | connect(ui->cache_directory_button, &QToolButton::pressed, this, | ||
| 30 | [this] { SetDirectory(DirectoryTarget::Cache, ui->cache_directory_edit); }); | ||
| 31 | 29 | ||
| 32 | connect(ui->reset_game_list_cache, &QPushButton::pressed, this, | 30 | connect(ui->reset_game_list_cache, &QPushButton::pressed, this, |
| 33 | &ConfigureFilesystem::ResetMetadata); | 31 | &ConfigureFilesystem::ResetMetadata); |
| @@ -50,8 +48,6 @@ void ConfigureFilesystem::setConfiguration() { | |||
| 50 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::DumpDir))); | 48 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::DumpDir))); |
| 51 | ui->load_path_edit->setText( | 49 | ui->load_path_edit->setText( |
| 52 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::LoadDir))); | 50 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::LoadDir))); |
| 53 | ui->cache_directory_edit->setText( | ||
| 54 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))); | ||
| 55 | 51 | ||
| 56 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted); | 52 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted); |
| 57 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game); | 53 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game); |
| @@ -72,9 +68,6 @@ void ConfigureFilesystem::applyConfiguration() { | |||
| 72 | ui->dump_path_edit->text().toStdString()); | 68 | ui->dump_path_edit->text().toStdString()); |
| 73 | Common::FS::GetUserPath(Common::FS::UserPath::LoadDir, | 69 | Common::FS::GetUserPath(Common::FS::UserPath::LoadDir, |
| 74 | ui->load_path_edit->text().toStdString()); | 70 | ui->load_path_edit->text().toStdString()); |
| 75 | Common::FS::GetUserPath(Common::FS::UserPath::CacheDir, | ||
| 76 | ui->cache_directory_edit->text().toStdString()); | ||
| 77 | Settings::values.gamecard_path = ui->gamecard_path_edit->text().toStdString(); | ||
| 78 | 71 | ||
| 79 | Settings::values.gamecard_inserted = ui->gamecard_inserted->isChecked(); | 72 | Settings::values.gamecard_inserted = ui->gamecard_inserted->isChecked(); |
| 80 | Settings::values.gamecard_current_game = ui->gamecard_current_game->isChecked(); | 73 | Settings::values.gamecard_current_game = ui->gamecard_current_game->isChecked(); |
| @@ -103,9 +96,6 @@ void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit) | |||
| 103 | case DirectoryTarget::Load: | 96 | case DirectoryTarget::Load: |
| 104 | caption = tr("Select Mod Load Directory..."); | 97 | caption = tr("Select Mod Load Directory..."); |
| 105 | break; | 98 | break; |
| 106 | case DirectoryTarget::Cache: | ||
| 107 | caption = tr("Select Cache Directory..."); | ||
| 108 | break; | ||
| 109 | } | 99 | } |
| 110 | 100 | ||
| 111 | QString str; | 101 | QString str; |
diff --git a/src/yuzu/configuration/configure_filesystem.h b/src/yuzu/configuration/configure_filesystem.h index a79303760..2147cd405 100644 --- a/src/yuzu/configuration/configure_filesystem.h +++ b/src/yuzu/configuration/configure_filesystem.h | |||
| @@ -32,7 +32,6 @@ private: | |||
| 32 | Gamecard, | 32 | Gamecard, |
| 33 | Dump, | 33 | Dump, |
| 34 | Load, | 34 | Load, |
| 35 | Cache, | ||
| 36 | }; | 35 | }; |
| 37 | 36 | ||
| 38 | void SetDirectory(DirectoryTarget target, QLineEdit* edit); | 37 | void SetDirectory(DirectoryTarget target, QLineEdit* edit); |
diff --git a/src/yuzu/configuration/configure_filesystem.ui b/src/yuzu/configuration/configure_filesystem.ui index 84bea0600..62b9abc7a 100644 --- a/src/yuzu/configuration/configure_filesystem.ui +++ b/src/yuzu/configuration/configure_filesystem.ui | |||
| @@ -198,40 +198,7 @@ | |||
| 198 | <string>Caching</string> | 198 | <string>Caching</string> |
| 199 | </property> | 199 | </property> |
| 200 | <layout class="QGridLayout" name="gridLayout_5"> | 200 | <layout class="QGridLayout" name="gridLayout_5"> |
| 201 | <item row="0" column="0"> | 201 | <item row="0" column="0" colspan="2"> |
| 202 | <widget class="QLabel" name="label_10"> | ||
| 203 | <property name="text"> | ||
| 204 | <string>Cache Directory</string> | ||
| 205 | </property> | ||
| 206 | </widget> | ||
| 207 | </item> | ||
| 208 | <item row="0" column="1"> | ||
| 209 | <spacer name="horizontalSpacer_3"> | ||
| 210 | <property name="orientation"> | ||
| 211 | <enum>Qt::Horizontal</enum> | ||
| 212 | </property> | ||
| 213 | <property name="sizeType"> | ||
| 214 | <enum>QSizePolicy::Fixed</enum> | ||
| 215 | </property> | ||
| 216 | <property name="sizeHint" stdset="0"> | ||
| 217 | <size> | ||
| 218 | <width>40</width> | ||
| 219 | <height>20</height> | ||
| 220 | </size> | ||
| 221 | </property> | ||
| 222 | </spacer> | ||
| 223 | </item> | ||
| 224 | <item row="0" column="2"> | ||
| 225 | <widget class="QLineEdit" name="cache_directory_edit"/> | ||
| 226 | </item> | ||
| 227 | <item row="0" column="3"> | ||
| 228 | <widget class="QToolButton" name="cache_directory_button"> | ||
| 229 | <property name="text"> | ||
| 230 | <string>...</string> | ||
| 231 | </property> | ||
| 232 | </widget> | ||
| 233 | </item> | ||
| 234 | <item row="1" column="0" colspan="4"> | ||
| 235 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 202 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 236 | <item> | 203 | <item> |
| 237 | <widget class="QCheckBox" name="cache_game_list"> | 204 | <widget class="QCheckBox" name="cache_game_list"> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index aa0a9f288..6d8bc5509 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -329,9 +329,6 @@ void Config::ReadValues() { | |||
| 329 | FS::GetUserPath( | 329 | FS::GetUserPath( |
| 330 | FS::UserPath::DumpDir, | 330 | FS::UserPath::DumpDir, |
| 331 | sdl2_config->Get("Data Storage", "dump_directory", FS::GetUserPath(FS::UserPath::DumpDir))); | 331 | sdl2_config->Get("Data Storage", "dump_directory", FS::GetUserPath(FS::UserPath::DumpDir))); |
| 332 | FS::GetUserPath(FS::UserPath::CacheDir, | ||
| 333 | sdl2_config->Get("Data Storage", "cache_directory", | ||
| 334 | FS::GetUserPath(FS::UserPath::CacheDir))); | ||
| 335 | Settings::values.gamecard_inserted = | 332 | Settings::values.gamecard_inserted = |
| 336 | sdl2_config->GetBoolean("Data Storage", "gamecard_inserted", false); | 333 | sdl2_config->GetBoolean("Data Storage", "gamecard_inserted", false); |
| 337 | Settings::values.gamecard_current_game = | 334 | Settings::values.gamecard_current_game = |