diff options
| -rw-r--r-- | src/input_common/drivers/udp_client.cpp | 74 | ||||
| -rw-r--r-- | src/input_common/helpers/udp_protocol.h | 21 | ||||
| -rw-r--r-- | src/tests/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/tests/input_common/calibration_configuration_job.cpp | 136 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 50 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.cpp | 123 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/blit_image.h | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.cpp | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 34 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 8 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 15 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/game_list.cpp | 19 | ||||
| -rw-r--r-- | src/yuzu/uisettings.h | 3 |
15 files changed, 354 insertions, 203 deletions
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index 4ab991a7d..a1ce4525d 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp | |||
| @@ -536,42 +536,46 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 536 | std::function<void(u16, u16, u16, u16)> data_callback) { | 536 | std::function<void(u16, u16, u16, u16)> data_callback) { |
| 537 | 537 | ||
| 538 | std::thread([=, this] { | 538 | std::thread([=, this] { |
| 539 | u16 min_x{UINT16_MAX}; | ||
| 540 | u16 min_y{UINT16_MAX}; | ||
| 541 | u16 max_x{}; | ||
| 542 | u16 max_y{}; | ||
| 543 | |||
| 539 | Status current_status{Status::Initialized}; | 544 | Status current_status{Status::Initialized}; |
| 540 | SocketCallback callback{ | 545 | SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, |
| 541 | [](Response::Version) {}, [](Response::PortInfo) {}, | 546 | [&](Response::PadData data) { |
| 542 | [&](Response::PadData data) { | 547 | constexpr u16 CALIBRATION_THRESHOLD = 100; |
| 543 | static constexpr u16 CALIBRATION_THRESHOLD = 100; | 548 | |
| 544 | static constexpr u16 MAX_VALUE = UINT16_MAX; | 549 | if (current_status == Status::Initialized) { |
| 545 | 550 | // Receiving data means the communication is ready now | |
| 546 | if (current_status == Status::Initialized) { | 551 | current_status = Status::Ready; |
| 547 | // Receiving data means the communication is ready now | 552 | status_callback(current_status); |
| 548 | current_status = Status::Ready; | 553 | } |
| 549 | status_callback(current_status); | 554 | if (data.touch[0].is_active == 0) { |
| 550 | } | 555 | return; |
| 551 | const auto& touchpad_0 = data.touch[0]; | 556 | } |
| 552 | if (touchpad_0.is_active == 0) { | 557 | LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, |
| 553 | return; | 558 | data.touch[0].y); |
| 554 | } | 559 | min_x = std::min(min_x, static_cast<u16>(data.touch[0].x)); |
| 555 | LOG_DEBUG(Input, "Current touch: {} {}", touchpad_0.x, touchpad_0.y); | 560 | min_y = std::min(min_y, static_cast<u16>(data.touch[0].y)); |
| 556 | const u16 min_x = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.x)); | 561 | if (current_status == Status::Ready) { |
| 557 | const u16 min_y = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.y)); | 562 | // First touch - min data (min_x/min_y) |
| 558 | if (current_status == Status::Ready) { | 563 | current_status = Status::Stage1Completed; |
| 559 | // First touch - min data (min_x/min_y) | 564 | status_callback(current_status); |
| 560 | current_status = Status::Stage1Completed; | 565 | } |
| 561 | status_callback(current_status); | 566 | if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && |
| 562 | } | 567 | data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { |
| 563 | if (touchpad_0.x - min_x > CALIBRATION_THRESHOLD && | 568 | // Set the current position as max value and finishes |
| 564 | touchpad_0.y - min_y > CALIBRATION_THRESHOLD) { | 569 | // configuration |
| 565 | // Set the current position as max value and finishes configuration | 570 | max_x = data.touch[0].x; |
| 566 | const u16 max_x = touchpad_0.x; | 571 | max_y = data.touch[0].y; |
| 567 | const u16 max_y = touchpad_0.y; | 572 | current_status = Status::Completed; |
| 568 | current_status = Status::Completed; | 573 | data_callback(min_x, min_y, max_x, max_y); |
| 569 | data_callback(min_x, min_y, max_x, max_y); | 574 | status_callback(current_status); |
| 570 | status_callback(current_status); | 575 | |
| 571 | 576 | complete_event.Set(); | |
| 572 | complete_event.Set(); | 577 | } |
| 573 | } | 578 | }}; |
| 574 | }}; | ||
| 575 | Socket socket{host, port, std::move(callback)}; | 579 | Socket socket{host, port, std::move(callback)}; |
| 576 | std::thread worker_thread{SocketLoop, &socket}; | 580 | std::thread worker_thread{SocketLoop, &socket}; |
| 577 | complete_event.Wait(); | 581 | complete_event.Wait(); |
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h index bcba12c58..2d5d54ddb 100644 --- a/src/input_common/helpers/udp_protocol.h +++ b/src/input_common/helpers/udp_protocol.h | |||
| @@ -54,6 +54,18 @@ struct Message { | |||
| 54 | template <typename T> | 54 | template <typename T> |
| 55 | constexpr Type GetMessageType(); | 55 | constexpr Type GetMessageType(); |
| 56 | 56 | ||
| 57 | template <typename T> | ||
| 58 | Message<T> CreateMessage(const u32 magic, const T data, const u32 sender_id) { | ||
| 59 | boost::crc_32_type crc; | ||
| 60 | Header header{ | ||
| 61 | magic, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, sender_id, GetMessageType<T>(), | ||
| 62 | }; | ||
| 63 | Message<T> message{header, data}; | ||
| 64 | crc.process_bytes(&message, sizeof(Message<T>)); | ||
| 65 | message.header.crc = crc.checksum(); | ||
| 66 | return message; | ||
| 67 | } | ||
| 68 | |||
| 57 | namespace Request { | 69 | namespace Request { |
| 58 | 70 | ||
| 59 | enum RegisterFlags : u8 { | 71 | enum RegisterFlags : u8 { |
| @@ -101,14 +113,7 @@ static_assert(std::is_trivially_copyable_v<PadData>, | |||
| 101 | */ | 113 | */ |
| 102 | template <typename T> | 114 | template <typename T> |
| 103 | Message<T> Create(const T data, const u32 client_id = 0) { | 115 | Message<T> Create(const T data, const u32 client_id = 0) { |
| 104 | boost::crc_32_type crc; | 116 | return CreateMessage(CLIENT_MAGIC, data, client_id); |
| 105 | Header header{ | ||
| 106 | CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType<T>(), | ||
| 107 | }; | ||
| 108 | Message<T> message{header, data}; | ||
| 109 | crc.process_bytes(&message, sizeof(Message<T>)); | ||
| 110 | message.header.crc = crc.checksum(); | ||
| 111 | return message; | ||
| 112 | } | 117 | } |
| 113 | } // namespace Request | 118 | } // namespace Request |
| 114 | 119 | ||
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index c4c012f3d..4a20c0768 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -10,11 +10,12 @@ add_executable(tests | |||
| 10 | core/network/network.cpp | 10 | core/network/network.cpp |
| 11 | tests.cpp | 11 | tests.cpp |
| 12 | video_core/buffer_base.cpp | 12 | video_core/buffer_base.cpp |
| 13 | input_common/calibration_configuration_job.cpp | ||
| 13 | ) | 14 | ) |
| 14 | 15 | ||
| 15 | create_target_directory_groups(tests) | 16 | create_target_directory_groups(tests) |
| 16 | 17 | ||
| 17 | target_link_libraries(tests PRIVATE common core) | 18 | target_link_libraries(tests PRIVATE common core input_common) |
| 18 | target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads) | 19 | target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads) |
| 19 | 20 | ||
| 20 | add_test(NAME tests COMMAND tests) | 21 | add_test(NAME tests COMMAND tests) |
diff --git a/src/tests/input_common/calibration_configuration_job.cpp b/src/tests/input_common/calibration_configuration_job.cpp new file mode 100644 index 000000000..8c77d81e9 --- /dev/null +++ b/src/tests/input_common/calibration_configuration_job.cpp | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <string> | ||
| 7 | #include <thread> | ||
| 8 | #include <boost/asio.hpp> | ||
| 9 | #include <boost/crc.hpp> | ||
| 10 | #include <catch2/catch.hpp> | ||
| 11 | |||
| 12 | #include "input_common/drivers/udp_client.h" | ||
| 13 | #include "input_common/helpers/udp_protocol.h" | ||
| 14 | |||
| 15 | class FakeCemuhookServer { | ||
| 16 | public: | ||
| 17 | FakeCemuhookServer() | ||
| 18 | : socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {} | ||
| 19 | |||
| 20 | ~FakeCemuhookServer() { | ||
| 21 | is_running = false; | ||
| 22 | boost::system::error_code error_code; | ||
| 23 | socket.shutdown(boost::asio::socket_base::shutdown_both, error_code); | ||
| 24 | socket.close(); | ||
| 25 | if (handler.joinable()) { | ||
| 26 | handler.join(); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | u16 GetPort() { | ||
| 31 | return socket.local_endpoint().port(); | ||
| 32 | } | ||
| 33 | |||
| 34 | std::string GetHost() { | ||
| 35 | return socket.local_endpoint().address().to_string(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void Run(const std::vector<InputCommon::CemuhookUDP::Response::TouchPad> touch_movement_path) { | ||
| 39 | constexpr size_t HeaderSize = sizeof(InputCommon::CemuhookUDP::Header); | ||
| 40 | constexpr size_t PadDataSize = | ||
| 41 | sizeof(InputCommon::CemuhookUDP::Message<InputCommon::CemuhookUDP::Response::PadData>); | ||
| 42 | |||
| 43 | REQUIRE(touch_movement_path.size() > 0); | ||
| 44 | is_running = true; | ||
| 45 | handler = std::thread([touch_movement_path, this]() { | ||
| 46 | auto current_touch_position = touch_movement_path.begin(); | ||
| 47 | while (is_running) { | ||
| 48 | boost::asio::ip::udp::endpoint sender_endpoint; | ||
| 49 | boost::system::error_code error_code; | ||
| 50 | auto received_size = socket.receive_from(boost::asio::buffer(receive_buffer), | ||
| 51 | sender_endpoint, 0, error_code); | ||
| 52 | |||
| 53 | if (received_size < HeaderSize) { | ||
| 54 | continue; | ||
| 55 | } | ||
| 56 | |||
| 57 | InputCommon::CemuhookUDP::Header header{}; | ||
| 58 | std::memcpy(&header, receive_buffer.data(), HeaderSize); | ||
| 59 | switch (header.type) { | ||
| 60 | case InputCommon::CemuhookUDP::Type::PadData: { | ||
| 61 | InputCommon::CemuhookUDP::Response::PadData pad_data{}; | ||
| 62 | pad_data.touch[0] = *current_touch_position; | ||
| 63 | const auto pad_message = InputCommon::CemuhookUDP::CreateMessage( | ||
| 64 | InputCommon::CemuhookUDP::SERVER_MAGIC, pad_data, 0); | ||
| 65 | std::memcpy(send_buffer.data(), &pad_message, PadDataSize); | ||
| 66 | socket.send_to(boost::asio::buffer(send_buffer, PadDataSize), sender_endpoint, | ||
| 67 | 0, error_code); | ||
| 68 | |||
| 69 | bool can_advance = | ||
| 70 | std::next(current_touch_position) != touch_movement_path.end(); | ||
| 71 | if (can_advance) { | ||
| 72 | std::advance(current_touch_position, 1); | ||
| 73 | } | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | case InputCommon::CemuhookUDP::Type::PortInfo: | ||
| 77 | case InputCommon::CemuhookUDP::Type::Version: | ||
| 78 | default: | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | }); | ||
| 83 | } | ||
| 84 | |||
| 85 | private: | ||
| 86 | boost::asio::io_service io_service; | ||
| 87 | boost::asio::ip::udp::socket socket; | ||
| 88 | std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer; | ||
| 89 | std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer; | ||
| 90 | bool is_running = false; | ||
| 91 | std::thread handler; | ||
| 92 | }; | ||
| 93 | |||
| 94 | TEST_CASE("CalibrationConfigurationJob completed", "[input_common]") { | ||
| 95 | Common::Event complete_event; | ||
| 96 | FakeCemuhookServer server; | ||
| 97 | server.Run({{ | ||
| 98 | .is_active = 1, | ||
| 99 | .x = 0, | ||
| 100 | .y = 0, | ||
| 101 | }, | ||
| 102 | { | ||
| 103 | .is_active = 1, | ||
| 104 | .x = 200, | ||
| 105 | .y = 200, | ||
| 106 | }}); | ||
| 107 | |||
| 108 | InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status{}; | ||
| 109 | u16 min_x{}; | ||
| 110 | u16 min_y{}; | ||
| 111 | u16 max_x{}; | ||
| 112 | u16 max_y{}; | ||
| 113 | InputCommon::CemuhookUDP::CalibrationConfigurationJob job( | ||
| 114 | server.GetHost(), server.GetPort(), | ||
| 115 | [&status, | ||
| 116 | &complete_event](InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status_) { | ||
| 117 | status = status_; | ||
| 118 | if (status == | ||
| 119 | InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed) { | ||
| 120 | complete_event.Set(); | ||
| 121 | } | ||
| 122 | }, | ||
| 123 | [&](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) { | ||
| 124 | min_x = min_x_; | ||
| 125 | min_y = min_y_; | ||
| 126 | max_x = max_x_; | ||
| 127 | max_y = max_y_; | ||
| 128 | }); | ||
| 129 | |||
| 130 | complete_event.WaitUntil(std::chrono::system_clock::now() + std::chrono::seconds(10)); | ||
| 131 | REQUIRE(status == InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed); | ||
| 132 | REQUIRE(min_x == 0); | ||
| 133 | REQUIRE(min_y == 0); | ||
| 134 | REQUIRE(max_x == 200); | ||
| 135 | REQUIRE(max_y == 200); | ||
| 136 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 37d5e6a6b..dbf1df79c 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -92,7 +92,7 @@ public: | |||
| 92 | 92 | ||
| 93 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 93 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 94 | 94 | ||
| 95 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { | 95 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { |
| 96 | UNIMPLEMENTED(); | 96 | UNIMPLEMENTED(); |
| 97 | } | 97 | } |
| 98 | 98 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 28daacd82..f81c1b233 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -437,39 +437,29 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 437 | 437 | ||
| 438 | glBindTextureUnit(0, fxaa_texture.handle); | 438 | glBindTextureUnit(0, fxaa_texture.handle); |
| 439 | } | 439 | } |
| 440 | |||
| 441 | // Set projection matrix | ||
| 442 | const std::array ortho_matrix = | 440 | const std::array ortho_matrix = |
| 443 | MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); | 441 | MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); |
| 444 | 442 | ||
| 445 | GLuint fragment_handle; | 443 | const auto fragment_handle = [this]() { |
| 446 | const auto filter = Settings::values.scaling_filter.GetValue(); | 444 | switch (Settings::values.scaling_filter.GetValue()) { |
| 447 | switch (filter) { | 445 | case Settings::ScalingFilter::NearestNeighbor: |
| 448 | case Settings::ScalingFilter::NearestNeighbor: | 446 | case Settings::ScalingFilter::Bilinear: |
| 449 | fragment_handle = present_bilinear_fragment.handle; | 447 | return present_bilinear_fragment.handle; |
| 450 | break; | 448 | case Settings::ScalingFilter::Bicubic: |
| 451 | case Settings::ScalingFilter::Bilinear: | 449 | return present_bicubic_fragment.handle; |
| 452 | fragment_handle = present_bilinear_fragment.handle; | 450 | case Settings::ScalingFilter::Gaussian: |
| 453 | break; | 451 | return present_gaussian_fragment.handle; |
| 454 | case Settings::ScalingFilter::Bicubic: | 452 | case Settings::ScalingFilter::ScaleForce: |
| 455 | fragment_handle = present_bicubic_fragment.handle; | 453 | return present_scaleforce_fragment.handle; |
| 456 | break; | 454 | case Settings::ScalingFilter::Fsr: |
| 457 | case Settings::ScalingFilter::Gaussian: | 455 | LOG_WARNING( |
| 458 | fragment_handle = present_gaussian_fragment.handle; | 456 | Render_OpenGL, |
| 459 | break; | 457 | "FidelityFX Super Resolution is not supported in OpenGL, changing to ScaleForce"); |
| 460 | case Settings::ScalingFilter::ScaleForce: | 458 | return present_scaleforce_fragment.handle; |
| 461 | fragment_handle = present_scaleforce_fragment.handle; | 459 | default: |
| 462 | break; | 460 | return present_bilinear_fragment.handle; |
| 463 | case Settings::ScalingFilter::Fsr: | 461 | } |
| 464 | LOG_WARNING( | 462 | }(); |
| 465 | Render_OpenGL, | ||
| 466 | "FidelityFX FSR Super Sampling is not supported in OpenGL, changing to ScaleForce"); | ||
| 467 | fragment_handle = present_scaleforce_fragment.handle; | ||
| 468 | break; | ||
| 469 | default: | ||
| 470 | fragment_handle = present_bilinear_fragment.handle; | ||
| 471 | break; | ||
| 472 | } | ||
| 473 | program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); | 463 | program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); |
| 474 | glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, | 464 | glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, |
| 475 | ortho_matrix.data()); | 465 | ortho_matrix.data()); |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 9a38b6b34..cd5995897 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | 6 | ||
| 7 | #include "common/settings.h" | ||
| 7 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" | 8 | #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" |
| 8 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" | 9 | #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" |
| 9 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" | 10 | #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" |
| @@ -335,6 +336,17 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi | |||
| 335 | cmdbuf.SetScissor(0, scissor); | 336 | cmdbuf.SetScissor(0, scissor); |
| 336 | cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); | 337 | cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); |
| 337 | } | 338 | } |
| 339 | |||
| 340 | VkExtent2D GetConversionExtent(const ImageView& src_image_view) { | ||
| 341 | const auto& resolution = Settings::values.resolution_info; | ||
| 342 | const bool is_rescaled = src_image_view.IsRescaled(); | ||
| 343 | u32 width = src_image_view.size.width; | ||
| 344 | u32 height = src_image_view.size.height; | ||
| 345 | return VkExtent2D{ | ||
| 346 | .width = is_rescaled ? resolution.ScaleUp(width) : width, | ||
| 347 | .height = is_rescaled ? resolution.ScaleUp(height) : height, | ||
| 348 | }; | ||
| 349 | } | ||
| 338 | } // Anonymous namespace | 350 | } // Anonymous namespace |
| 339 | 351 | ||
| 340 | BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | 352 | BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, |
| @@ -425,61 +437,52 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | |||
| 425 | } | 437 | } |
| 426 | 438 | ||
| 427 | void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, | 439 | void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, |
| 428 | const ImageView& src_image_view, u32 up_scale, | 440 | const ImageView& src_image_view) { |
| 429 | u32 down_shift) { | ||
| 430 | ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); | 441 | ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); |
| 431 | Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 442 | Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view); |
| 432 | } | 443 | } |
| 433 | 444 | ||
| 434 | void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, | 445 | void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, |
| 435 | const ImageView& src_image_view, u32 up_scale, | 446 | const ImageView& src_image_view) { |
| 436 | u32 down_shift) { | ||
| 437 | ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); | 447 | ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); |
| 438 | Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 448 | Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); |
| 439 | } | 449 | } |
| 440 | 450 | ||
| 441 | void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, | 451 | void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, |
| 442 | const ImageView& src_image_view, u32 up_scale, | 452 | const ImageView& src_image_view) { |
| 443 | u32 down_shift) { | ||
| 444 | ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); | 453 | ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); |
| 445 | Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 454 | Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view); |
| 446 | } | 455 | } |
| 447 | 456 | ||
| 448 | void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, | 457 | void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, |
| 449 | const ImageView& src_image_view, u32 up_scale, | 458 | const ImageView& src_image_view) { |
| 450 | u32 down_shift) { | ||
| 451 | ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); | 459 | ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); |
| 452 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); | 460 | Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); |
| 453 | } | 461 | } |
| 454 | 462 | ||
| 455 | void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, | 463 | void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, |
| 456 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 464 | const ImageView& src_image_view) { |
| 457 | ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), | 465 | ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), |
| 458 | convert_abgr8_to_d24s8_frag, true); | 466 | convert_abgr8_to_d24s8_frag); |
| 459 | ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, | 467 | Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view); |
| 460 | down_shift); | ||
| 461 | } | 468 | } |
| 462 | 469 | ||
| 463 | void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, | 470 | void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, |
| 464 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 471 | ImageView& src_image_view) { |
| 465 | ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), | 472 | ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), |
| 466 | convert_d24s8_to_abgr8_frag, false); | 473 | convert_d24s8_to_abgr8_frag); |
| 467 | ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale, | 474 | ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view); |
| 468 | down_shift); | ||
| 469 | } | 475 | } |
| 470 | 476 | ||
| 471 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 477 | void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 472 | const ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 478 | const ImageView& src_image_view) { |
| 473 | const VkPipelineLayout layout = *one_texture_pipeline_layout; | 479 | const VkPipelineLayout layout = *one_texture_pipeline_layout; |
| 474 | const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); | 480 | const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); |
| 475 | const VkSampler sampler = *nearest_sampler; | 481 | const VkSampler sampler = *nearest_sampler; |
| 476 | const VkExtent2D extent{ | 482 | const VkExtent2D extent = GetConversionExtent(src_image_view); |
| 477 | .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), | 483 | |
| 478 | .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U), | ||
| 479 | }; | ||
| 480 | scheduler.RequestRenderpass(dst_framebuffer); | 484 | scheduler.RequestRenderpass(dst_framebuffer); |
| 481 | scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift, | 485 | scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) { |
| 482 | this](vk::CommandBuffer cmdbuf) { | ||
| 483 | const VkOffset2D offset{ | 486 | const VkOffset2D offset{ |
| 484 | .x = 0, | 487 | .x = 0, |
| 485 | .y = 0, | 488 | .y = 0, |
| @@ -563,18 +566,16 @@ void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_f | |||
| 563 | } | 566 | } |
| 564 | 567 | ||
| 565 | void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 568 | void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 566 | ImageView& src_image_view, u32 up_scale, u32 down_shift) { | 569 | ImageView& src_image_view) { |
| 567 | const VkPipelineLayout layout = *two_textures_pipeline_layout; | 570 | const VkPipelineLayout layout = *two_textures_pipeline_layout; |
| 568 | const VkImageView src_depth_view = src_image_view.DepthView(); | 571 | const VkImageView src_depth_view = src_image_view.DepthView(); |
| 569 | const VkImageView src_stencil_view = src_image_view.StencilView(); | 572 | const VkImageView src_stencil_view = src_image_view.StencilView(); |
| 570 | const VkSampler sampler = *nearest_sampler; | 573 | const VkSampler sampler = *nearest_sampler; |
| 571 | const VkExtent2D extent{ | 574 | const VkExtent2D extent = GetConversionExtent(src_image_view); |
| 572 | .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), | 575 | |
| 573 | .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U), | ||
| 574 | }; | ||
| 575 | scheduler.RequestRenderpass(dst_framebuffer); | 576 | scheduler.RequestRenderpass(dst_framebuffer); |
| 576 | scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale, | 577 | scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, |
| 577 | down_shift, this](vk::CommandBuffer cmdbuf) { | 578 | this](vk::CommandBuffer cmdbuf) { |
| 578 | const VkOffset2D offset{ | 579 | const VkOffset2D offset{ |
| 579 | .x = 0, | 580 | .x = 0, |
| 580 | .y = 0, | 581 | .y = 0, |
| @@ -695,11 +696,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip | |||
| 695 | return *blit_depth_stencil_pipelines.back(); | 696 | return *blit_depth_stencil_pipelines.back(); |
| 696 | } | 697 | } |
| 697 | 698 | ||
| 698 | void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { | 699 | void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 700 | bool is_target_depth) { | ||
| 699 | if (pipeline) { | 701 | if (pipeline) { |
| 700 | return; | 702 | return; |
| 701 | } | 703 | } |
| 702 | const std::array stages = MakeStages(*full_screen_vert, *convert_depth_to_float_frag); | 704 | VkShaderModule frag_shader = |
| 705 | is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; | ||
| 706 | const std::array stages = MakeStages(*full_screen_vert, frag_shader); | ||
| 703 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | 707 | pipeline = device.GetLogical().CreateGraphicsPipeline({ |
| 704 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 708 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| 705 | .pNext = nullptr, | 709 | .pNext = nullptr, |
| @@ -712,8 +716,9 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend | |||
| 712 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | 716 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, |
| 713 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | 717 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, |
| 714 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | 718 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, |
| 715 | .pDepthStencilState = nullptr, | 719 | .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr, |
| 716 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, | 720 | .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO |
| 721 | : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, | ||
| 717 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | 722 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, |
| 718 | .layout = *one_texture_pipeline_layout, | 723 | .layout = *one_texture_pipeline_layout, |
| 719 | .renderPass = renderpass, | 724 | .renderPass = renderpass, |
| @@ -723,37 +728,17 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend | |||
| 723 | }); | 728 | }); |
| 724 | } | 729 | } |
| 725 | 730 | ||
| 731 | void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { | ||
| 732 | ConvertPipeline(pipeline, renderpass, false); | ||
| 733 | } | ||
| 734 | |||
| 726 | void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { | 735 | void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { |
| 727 | if (pipeline) { | 736 | ConvertPipeline(pipeline, renderpass, true); |
| 728 | return; | ||
| 729 | } | ||
| 730 | const std::array stages = MakeStages(*full_screen_vert, *convert_float_to_depth_frag); | ||
| 731 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | ||
| 732 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||
| 733 | .pNext = nullptr, | ||
| 734 | .flags = 0, | ||
| 735 | .stageCount = static_cast<u32>(stages.size()), | ||
| 736 | .pStages = stages.data(), | ||
| 737 | .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | ||
| 738 | .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, | ||
| 739 | .pTessellationState = nullptr, | ||
| 740 | .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, | ||
| 741 | .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, | ||
| 742 | .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, | ||
| 743 | .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, | ||
| 744 | .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, | ||
| 745 | .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, | ||
| 746 | .layout = *one_texture_pipeline_layout, | ||
| 747 | .renderPass = renderpass, | ||
| 748 | .subpass = 0, | ||
| 749 | .basePipelineHandle = VK_NULL_HANDLE, | ||
| 750 | .basePipelineIndex = 0, | ||
| 751 | }); | ||
| 752 | } | 737 | } |
| 753 | 738 | ||
| 754 | void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 739 | void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 755 | vk::ShaderModule& module, bool is_target_depth, | 740 | vk::ShaderModule& module, bool single_texture, |
| 756 | bool single_texture) { | 741 | bool is_target_depth) { |
| 757 | if (pipeline) { | 742 | if (pipeline) { |
| 758 | return; | 743 | return; |
| 759 | } | 744 | } |
| @@ -782,13 +767,13 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren | |||
| 782 | } | 767 | } |
| 783 | 768 | ||
| 784 | void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 769 | void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 785 | vk::ShaderModule& module, bool single_texture) { | 770 | vk::ShaderModule& module) { |
| 786 | ConvertPipelineEx(pipeline, renderpass, module, false, single_texture); | 771 | ConvertPipelineEx(pipeline, renderpass, module, false, false); |
| 787 | } | 772 | } |
| 788 | 773 | ||
| 789 | void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 774 | void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 790 | vk::ShaderModule& module, bool single_texture) { | 775 | vk::ShaderModule& module) { |
| 791 | ConvertPipelineEx(pipeline, renderpass, module, true, single_texture); | 776 | ConvertPipelineEx(pipeline, renderpass, module, true, true); |
| 792 | } | 777 | } |
| 793 | 778 | ||
| 794 | } // namespace Vulkan | 779 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index b1a717090..1d9f61a52 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -44,50 +44,46 @@ public: | |||
| 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, | 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 45 | Tegra::Engines::Fermi2D::Operation operation); | 45 | Tegra::Engines::Fermi2D::Operation operation); |
| 46 | 46 | ||
| 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
| 48 | u32 up_scale, u32 down_shift); | ||
| 49 | 48 | ||
| 50 | void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 49 | void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
| 51 | u32 up_scale, u32 down_shift); | ||
| 52 | 50 | ||
| 53 | void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 51 | void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
| 54 | u32 up_scale, u32 down_shift); | ||
| 55 | 52 | ||
| 56 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 53 | void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
| 57 | u32 up_scale, u32 down_shift); | ||
| 58 | 54 | ||
| 59 | void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | 55 | void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
| 60 | u32 up_scale, u32 down_shift); | ||
| 61 | 56 | ||
| 62 | void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, | 57 | void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view); |
| 63 | u32 up_scale, u32 down_shift); | ||
| 64 | 58 | ||
| 65 | private: | 59 | private: |
| 66 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 60 | void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 67 | const ImageView& src_image_view, u32 up_scale, u32 down_shift); | 61 | const ImageView& src_image_view); |
| 68 | 62 | ||
| 69 | void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 63 | void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 70 | ImageView& src_image_view, u32 up_scale, u32 down_shift); | 64 | ImageView& src_image_view, u32 up_scale, u32 down_shift); |
| 71 | 65 | ||
| 72 | void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, | 66 | void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, |
| 73 | ImageView& src_image_view, u32 up_scale, u32 down_shift); | 67 | ImageView& src_image_view); |
| 74 | 68 | ||
| 75 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); | 69 | [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); |
| 76 | 70 | ||
| 77 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); | 71 | [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); |
| 78 | 72 | ||
| 73 | void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); | ||
| 74 | |||
| 79 | void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); | 75 | void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); |
| 80 | 76 | ||
| 81 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); | 77 | void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); |
| 82 | 78 | ||
| 83 | void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 79 | void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 84 | vk::ShaderModule& module, bool is_target_depth, bool single_texture); | 80 | vk::ShaderModule& module, bool single_texture, bool is_target_depth); |
| 85 | 81 | ||
| 86 | void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 82 | void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 87 | vk::ShaderModule& module, bool single_texture); | 83 | vk::ShaderModule& module); |
| 88 | 84 | ||
| 89 | void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, | 85 | void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, |
| 90 | vk::ShaderModule& module, bool single_texture); | 86 | vk::ShaderModule& module); |
| 91 | 87 | ||
| 92 | const Device& device; | 88 | const Device& device; |
| 93 | VKScheduler& scheduler; | 89 | VKScheduler& scheduler; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 1e447e621..c71a1f44d 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -391,28 +391,23 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | |||
| 391 | .offset = {0, 0}, | 391 | .offset = {0, 0}, |
| 392 | .extent = size, | 392 | .extent = size, |
| 393 | }; | 393 | }; |
| 394 | const auto filter = Settings::values.scaling_filter.GetValue(); | ||
| 395 | cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); | 394 | cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); |
| 396 | switch (filter) { | 395 | auto graphics_pipeline = [this]() { |
| 397 | case Settings::ScalingFilter::NearestNeighbor: | 396 | switch (Settings::values.scaling_filter.GetValue()) { |
| 398 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); | 397 | case Settings::ScalingFilter::NearestNeighbor: |
| 399 | break; | 398 | case Settings::ScalingFilter::Bilinear: |
| 400 | case Settings::ScalingFilter::Bilinear: | 399 | return *bilinear_pipeline; |
| 401 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); | 400 | case Settings::ScalingFilter::Bicubic: |
| 402 | break; | 401 | return *bicubic_pipeline; |
| 403 | case Settings::ScalingFilter::Bicubic: | 402 | case Settings::ScalingFilter::Gaussian: |
| 404 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline); | 403 | return *gaussian_pipeline; |
| 405 | break; | 404 | case Settings::ScalingFilter::ScaleForce: |
| 406 | case Settings::ScalingFilter::Gaussian: | 405 | return *scaleforce_pipeline; |
| 407 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline); | 406 | default: |
| 408 | break; | 407 | return *bilinear_pipeline; |
| 409 | case Settings::ScalingFilter::ScaleForce: | 408 | } |
| 410 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline); | 409 | }(); |
| 411 | break; | 410 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline); |
| 412 | default: | ||
| 413 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); | ||
| 414 | break; | ||
| 415 | } | ||
| 416 | cmdbuf.SetViewport(0, viewport); | 411 | cmdbuf.SetViewport(0, viewport); |
| 417 | cmdbuf.SetScissor(0, scissor); | 412 | cmdbuf.SetScissor(0, scissor); |
| 418 | 413 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 197cba8e3..1941170cb 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -1057,37 +1057,37 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst | |||
| 1057 | }); | 1057 | }); |
| 1058 | } | 1058 | } |
| 1059 | 1059 | ||
| 1060 | void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, | 1060 | void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { |
| 1061 | bool rescaled) { | ||
| 1062 | const u32 up_scale = rescaled ? resolution.up_scale : 1; | ||
| 1063 | const u32 down_shift = rescaled ? resolution.down_shift : 0; | ||
| 1064 | switch (dst_view.format) { | 1061 | switch (dst_view.format) { |
| 1065 | case PixelFormat::R16_UNORM: | 1062 | case PixelFormat::R16_UNORM: |
| 1066 | if (src_view.format == PixelFormat::D16_UNORM) { | 1063 | if (src_view.format == PixelFormat::D16_UNORM) { |
| 1067 | return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); | 1064 | return blit_image_helper.ConvertD16ToR16(dst, src_view); |
| 1068 | } | 1065 | } |
| 1069 | break; | 1066 | break; |
| 1070 | case PixelFormat::A8B8G8R8_UNORM: | 1067 | case PixelFormat::A8B8G8R8_UNORM: |
| 1071 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { | 1068 | if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { |
| 1072 | return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift); | 1069 | return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view); |
| 1073 | } | 1070 | } |
| 1074 | break; | 1071 | break; |
| 1075 | case PixelFormat::R32_FLOAT: | 1072 | case PixelFormat::R32_FLOAT: |
| 1076 | if (src_view.format == PixelFormat::D32_FLOAT) { | 1073 | if (src_view.format == PixelFormat::D32_FLOAT) { |
| 1077 | return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); | 1074 | return blit_image_helper.ConvertD32ToR32(dst, src_view); |
| 1078 | } | 1075 | } |
| 1079 | break; | 1076 | break; |
| 1080 | case PixelFormat::D16_UNORM: | 1077 | case PixelFormat::D16_UNORM: |
| 1081 | if (src_view.format == PixelFormat::R16_UNORM) { | 1078 | if (src_view.format == PixelFormat::R16_UNORM) { |
| 1082 | return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); | 1079 | return blit_image_helper.ConvertR16ToD16(dst, src_view); |
| 1083 | } | 1080 | } |
| 1084 | break; | 1081 | break; |
| 1085 | case PixelFormat::S8_UINT_D24_UNORM: | 1082 | case PixelFormat::S8_UINT_D24_UNORM: |
| 1086 | return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift); | 1083 | if (src_view.format == PixelFormat::A8B8G8R8_UNORM || |
| 1084 | src_view.format == PixelFormat::B8G8R8A8_UNORM) { | ||
| 1085 | return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view); | ||
| 1086 | } | ||
| 1087 | break; | 1087 | break; |
| 1088 | case PixelFormat::D32_FLOAT: | 1088 | case PixelFormat::D32_FLOAT: |
| 1089 | if (src_view.format == PixelFormat::R32_FLOAT) { | 1089 | if (src_view.format == PixelFormat::R32_FLOAT) { |
| 1090 | return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); | 1090 | return blit_image_helper.ConvertR32ToD32(dst, src_view); |
| 1091 | } | 1091 | } |
| 1092 | break; | 1092 | break; |
| 1093 | default: | 1093 | default: |
| @@ -1329,6 +1329,10 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm | |||
| 1329 | } | 1329 | } |
| 1330 | } | 1330 | } |
| 1331 | 1331 | ||
| 1332 | bool Image::IsRescaled() const noexcept { | ||
| 1333 | return True(flags & ImageFlagBits::Rescaled); | ||
| 1334 | } | ||
| 1335 | |||
| 1332 | bool Image::ScaleUp(bool ignore) { | 1336 | bool Image::ScaleUp(bool ignore) { |
| 1333 | if (True(flags & ImageFlagBits::Rescaled)) { | 1337 | if (True(flags & ImageFlagBits::Rescaled)) { |
| 1334 | return false; | 1338 | return false; |
| @@ -1469,7 +1473,8 @@ bool Image::BlitScaleHelper(bool scale_up) { | |||
| 1469 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, | 1473 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, |
| 1470 | ImageId image_id_, Image& image) | 1474 | ImageId image_id_, Image& image) |
| 1471 | : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, | 1475 | : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, |
| 1472 | image_handle{image.Handle()}, samples{ConvertSampleCount(image.info.num_samples)} { | 1476 | src_image{&image}, image_handle{image.Handle()}, |
| 1477 | samples(ConvertSampleCount(image.info.num_samples)) { | ||
| 1473 | using Shader::TextureType; | 1478 | using Shader::TextureType; |
| 1474 | 1479 | ||
| 1475 | const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); | 1480 | const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); |
| @@ -1607,6 +1612,13 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, | |||
| 1607 | return *view; | 1612 | return *view; |
| 1608 | } | 1613 | } |
| 1609 | 1614 | ||
| 1615 | bool ImageView::IsRescaled() const noexcept { | ||
| 1616 | if (!src_image) { | ||
| 1617 | return false; | ||
| 1618 | } | ||
| 1619 | return src_image->IsRescaled(); | ||
| 1620 | } | ||
| 1621 | |||
| 1610 | vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { | 1622 | vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { |
| 1611 | return device->GetLogical().CreateImageView({ | 1623 | return device->GetLogical().CreateImageView({ |
| 1612 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 1624 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 753e3e8a1..c592f2666 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -65,7 +65,7 @@ public: | |||
| 65 | 65 | ||
| 66 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 66 | void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 67 | 67 | ||
| 68 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); | 68 | void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); |
| 69 | 69 | ||
| 70 | bool CanAccelerateImageUpload(Image&) const noexcept { | 70 | bool CanAccelerateImageUpload(Image&) const noexcept { |
| 71 | return false; | 71 | return false; |
| @@ -139,6 +139,8 @@ public: | |||
| 139 | return std::exchange(initialized, true); | 139 | return std::exchange(initialized, true); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | bool IsRescaled() const noexcept; | ||
| 143 | |||
| 142 | bool ScaleUp(bool ignore = false); | 144 | bool ScaleUp(bool ignore = false); |
| 143 | 145 | ||
| 144 | bool ScaleDown(bool ignore = false); | 146 | bool ScaleDown(bool ignore = false); |
| @@ -189,6 +191,8 @@ public: | |||
| 189 | [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, | 191 | [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, |
| 190 | Shader::ImageFormat image_format); | 192 | Shader::ImageFormat image_format); |
| 191 | 193 | ||
| 194 | [[nodiscard]] bool IsRescaled() const noexcept; | ||
| 195 | |||
| 192 | [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { | 196 | [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { |
| 193 | return *image_views[static_cast<size_t>(texture_type)]; | 197 | return *image_views[static_cast<size_t>(texture_type)]; |
| 194 | } | 198 | } |
| @@ -222,6 +226,8 @@ private: | |||
| 222 | [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); | 226 | [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); |
| 223 | 227 | ||
| 224 | const Device* device = nullptr; | 228 | const Device* device = nullptr; |
| 229 | const Image* src_image{}; | ||
| 230 | |||
| 225 | std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; | 231 | std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; |
| 226 | std::unique_ptr<StorageViews> storage_views; | 232 | std::unique_ptr<StorageViews> storage_views; |
| 227 | vk::ImageView depth_view; | 233 | vk::ImageView depth_view; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 5aaeb16ca..2e19fced2 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1855,9 +1855,20 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag | |||
| 1855 | .height = std::min(dst_view.size.height, src_view.size.height), | 1855 | .height = std::min(dst_view.size.height, src_view.size.height), |
| 1856 | .depth = std::min(dst_view.size.depth, src_view.size.depth), | 1856 | .depth = std::min(dst_view.size.depth, src_view.size.depth), |
| 1857 | }; | 1857 | }; |
| 1858 | UNIMPLEMENTED_IF(copy.extent != expected_size); | 1858 | const Extent3D scaled_extent = [is_rescaled, expected_size]() { |
| 1859 | if (!is_rescaled) { | ||
| 1860 | return expected_size; | ||
| 1861 | } | ||
| 1862 | const auto& resolution = Settings::values.resolution_info; | ||
| 1863 | return Extent3D{ | ||
| 1864 | .width = resolution.ScaleUp(expected_size.width), | ||
| 1865 | .height = resolution.ScaleUp(expected_size.height), | ||
| 1866 | .depth = expected_size.depth, | ||
| 1867 | }; | ||
| 1868 | }(); | ||
| 1869 | UNIMPLEMENTED_IF(copy.extent != scaled_extent); | ||
| 1859 | 1870 | ||
| 1860 | runtime.ConvertImage(dst_framebuffer, dst_view, src_view, is_rescaled); | 1871 | runtime.ConvertImage(dst_framebuffer, dst_view, src_view); |
| 1861 | } | 1872 | } |
| 1862 | } | 1873 | } |
| 1863 | 1874 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 463d500c2..0f679c37e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -776,6 +776,7 @@ void Config::ReadUIGamelistValues() { | |||
| 776 | ReadBasicSetting(UISettings::values.row_1_text_id); | 776 | ReadBasicSetting(UISettings::values.row_1_text_id); |
| 777 | ReadBasicSetting(UISettings::values.row_2_text_id); | 777 | ReadBasicSetting(UISettings::values.row_2_text_id); |
| 778 | ReadBasicSetting(UISettings::values.cache_game_list); | 778 | ReadBasicSetting(UISettings::values.cache_game_list); |
| 779 | ReadBasicSetting(UISettings::values.favorites_expanded); | ||
| 779 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); | 780 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); |
| 780 | for (int i = 0; i < favorites_size; i++) { | 781 | for (int i = 0; i < favorites_size; i++) { |
| 781 | qt_config->setArrayIndex(i); | 782 | qt_config->setArrayIndex(i); |
| @@ -1300,6 +1301,7 @@ void Config::SaveUIGamelistValues() { | |||
| 1300 | WriteBasicSetting(UISettings::values.row_1_text_id); | 1301 | WriteBasicSetting(UISettings::values.row_1_text_id); |
| 1301 | WriteBasicSetting(UISettings::values.row_2_text_id); | 1302 | WriteBasicSetting(UISettings::values.row_2_text_id); |
| 1302 | WriteBasicSetting(UISettings::values.cache_game_list); | 1303 | WriteBasicSetting(UISettings::values.cache_game_list); |
| 1304 | WriteBasicSetting(UISettings::values.favorites_expanded); | ||
| 1303 | qt_config->beginWriteArray(QStringLiteral("favorites")); | 1305 | qt_config->beginWriteArray(QStringLiteral("favorites")); |
| 1304 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { | 1306 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { |
| 1305 | qt_config->setArrayIndex(i); | 1307 | qt_config->setArrayIndex(i); |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 1a5e41588..8b5c4a10a 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -173,13 +173,17 @@ void GameList::OnItemExpanded(const QModelIndex& item) { | |||
| 173 | const bool is_dir = type == GameListItemType::CustomDir || type == GameListItemType::SdmcDir || | 173 | const bool is_dir = type == GameListItemType::CustomDir || type == GameListItemType::SdmcDir || |
| 174 | type == GameListItemType::UserNandDir || | 174 | type == GameListItemType::UserNandDir || |
| 175 | type == GameListItemType::SysNandDir; | 175 | type == GameListItemType::SysNandDir; |
| 176 | 176 | const bool is_fave = type == GameListItemType::Favorites; | |
| 177 | if (!is_dir) { | 177 | if (!is_dir && !is_fave) { |
| 178 | return; | 178 | return; |
| 179 | } | 179 | } |
| 180 | 180 | const bool is_expanded = tree_view->isExpanded(item); | |
| 181 | UISettings::values.game_dirs[item.data(GameListDir::GameDirRole).toInt()].expanded = | 181 | if (is_fave) { |
| 182 | tree_view->isExpanded(item); | 182 | UISettings::values.favorites_expanded = is_expanded; |
| 183 | return; | ||
| 184 | } | ||
| 185 | const int item_dir_index = item.data(GameListDir::GameDirRole).toInt(); | ||
| 186 | UISettings::values.game_dirs[item_dir_index].expanded = is_expanded; | ||
| 183 | } | 187 | } |
| 184 | 188 | ||
| 185 | // Event in order to filter the gamelist after editing the searchfield | 189 | // Event in order to filter the gamelist after editing the searchfield |
| @@ -458,10 +462,13 @@ void GameList::DonePopulating(const QStringList& watch_list) { | |||
| 458 | emit ShowList(!IsEmpty()); | 462 | emit ShowList(!IsEmpty()); |
| 459 | 463 | ||
| 460 | item_model->invisibleRootItem()->appendRow(new GameListAddDir()); | 464 | item_model->invisibleRootItem()->appendRow(new GameListAddDir()); |
| 465 | |||
| 466 | // Add favorites row | ||
| 461 | item_model->invisibleRootItem()->insertRow(0, new GameListFavorites()); | 467 | item_model->invisibleRootItem()->insertRow(0, new GameListFavorites()); |
| 462 | tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), | 468 | tree_view->setRowHidden(0, item_model->invisibleRootItem()->index(), |
| 463 | UISettings::values.favorited_ids.size() == 0); | 469 | UISettings::values.favorited_ids.size() == 0); |
| 464 | tree_view->expand(item_model->invisibleRootItem()->child(0)->index()); | 470 | tree_view->setExpanded(item_model->invisibleRootItem()->child(0)->index(), |
| 471 | UISettings::values.favorites_expanded.GetValue()); | ||
| 465 | for (const auto id : UISettings::values.favorited_ids) { | 472 | for (const auto id : UISettings::values.favorited_ids) { |
| 466 | AddFavorite(id); | 473 | AddFavorite(id); |
| 467 | } | 474 | } |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 936914ef3..a610e7e25 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -74,7 +74,6 @@ struct Values { | |||
| 74 | QString game_dir_deprecated; | 74 | QString game_dir_deprecated; |
| 75 | bool game_dir_deprecated_deepscan; | 75 | bool game_dir_deprecated_deepscan; |
| 76 | QVector<UISettings::GameDir> game_dirs; | 76 | QVector<UISettings::GameDir> game_dirs; |
| 77 | QVector<u64> favorited_ids; | ||
| 78 | QStringList recent_files; | 77 | QStringList recent_files; |
| 79 | QString language; | 78 | QString language; |
| 80 | 79 | ||
| @@ -96,6 +95,8 @@ struct Values { | |||
| 96 | Settings::BasicSetting<uint8_t> row_2_text_id{2, "row_2_text_id"}; | 95 | Settings::BasicSetting<uint8_t> row_2_text_id{2, "row_2_text_id"}; |
| 97 | std::atomic_bool is_game_list_reload_pending{false}; | 96 | std::atomic_bool is_game_list_reload_pending{false}; |
| 98 | Settings::BasicSetting<bool> cache_game_list{true, "cache_game_list"}; | 97 | Settings::BasicSetting<bool> cache_game_list{true, "cache_game_list"}; |
| 98 | Settings::BasicSetting<bool> favorites_expanded{true, "favorites_expanded"}; | ||
| 99 | QVector<u64> favorited_ids; | ||
| 99 | 100 | ||
| 100 | bool configuration_applied; | 101 | bool configuration_applied; |
| 101 | bool reset_to_defaults; | 102 | bool reset_to_defaults; |