summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/uint128.h20
-rw-r--r--src/common/wall_clock.cpp15
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/hle/kernel/kernel.cpp9
-rw-r--r--src/core/hle/service/acc/acc.cpp18
-rw-r--r--src/core/hle/service/hid/hid.cpp123
-rw-r--r--src/core/hle/service/hid/hid.h10
-rw-r--r--src/core/hle/service/time/time_manager.cpp4
-rw-r--r--src/core/hle/service/time/time_manager.h2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp31
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h28
-rw-r--r--src/video_core/shader/decode/memory.cpp1
-rw-r--r--src/video_core/shader/decode/texture.cpp11
20 files changed, 265 insertions, 47 deletions
diff --git a/src/common/uint128.h b/src/common/uint128.h
index 83560a9ce..4780b2f9d 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -98,4 +98,24 @@ namespace Common {
98#endif 98#endif
99} 99}
100 100
101// This function divides a u128 by a u32 value and produces two u64 values:
102// the result of division and the remainder
103[[nodiscard]] static inline std::pair<u64, u64> Divide128On32(u128 dividend, u32 divisor) {
104 u64 remainder = dividend[0] % divisor;
105 u64 accum = dividend[0] / divisor;
106 if (dividend[1] == 0)
107 return {accum, remainder};
108 // We ignore dividend[1] / divisor as that overflows
109 const u64 first_segment = (dividend[1] % divisor) << 32;
110 accum += (first_segment / divisor) << 32;
111 const u64 second_segment = (first_segment % divisor) << 32;
112 accum += (second_segment / divisor);
113 remainder += second_segment % divisor;
114 if (remainder >= divisor) {
115 accum++;
116 remainder -= divisor;
117 }
118 return {accum, remainder};
119}
120
101} // namespace Common 121} // namespace Common
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 1545993bd..49830b8ab 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -20,9 +20,7 @@ using base_time_point = std::chrono::time_point<base_timer>;
20class StandardWallClock final : public WallClock { 20class StandardWallClock final : public WallClock {
21public: 21public:
22 explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_) 22 explicit StandardWallClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequency_)
23 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false), 23 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, false) {
24 emulated_clock_factor{GetFixedPoint64Factor(emulated_clock_frequency, 1000000000)},
25 emulated_cpu_factor{GetFixedPoint64Factor(emulated_cpu_frequency, 1000000000)} {
26 start_time = base_timer::now(); 24 start_time = base_timer::now();
27 } 25 }
28 26
@@ -45,11 +43,16 @@ public:
45 } 43 }
46 44
47 u64 GetClockCycles() override { 45 u64 GetClockCycles() override {
48 return MultiplyHigh(GetTimeNS().count(), emulated_clock_factor); 46 std::chrono::nanoseconds time_now = GetTimeNS();
47 const u128 temporary =
48 Common::Multiply64Into128(time_now.count(), emulated_clock_frequency);
49 return Common::Divide128On32(temporary, 1000000000).first;
49 } 50 }
50 51
51 u64 GetCPUCycles() override { 52 u64 GetCPUCycles() override {
52 return MultiplyHigh(GetTimeNS().count(), emulated_cpu_factor); 53 std::chrono::nanoseconds time_now = GetTimeNS();
54 const u128 temporary = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency);
55 return Common::Divide128On32(temporary, 1000000000).first;
53 } 56 }
54 57
55 void Pause([[maybe_unused]] bool is_paused) override { 58 void Pause([[maybe_unused]] bool is_paused) override {
@@ -58,8 +61,6 @@ public:
58 61
59private: 62private:
60 base_time_point start_time; 63 base_time_point start_time;
61 const u64 emulated_clock_factor;
62 const u64 emulated_cpu_factor;
63}; 64};
64 65
65#ifdef ARCHITECTURE_x86_64 66#ifdef ARCHITECTURE_x86_64
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 30f5e1128..de6305e2a 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -308,6 +308,9 @@ struct System::Impl {
308 // Close all CPU/threading state 308 // Close all CPU/threading state
309 cpu_manager.Shutdown(); 309 cpu_manager.Shutdown();
310 310
311 // Release the Time Manager's resources
312 time_manager.Shutdown();
313
311 // Shutdown kernel and core timing 314 // Shutdown kernel and core timing
312 core_timing.Shutdown(); 315 core_timing.Shutdown();
313 kernel.Shutdown(); 316 kernel.Shutdown();
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 453695545..331cf3a60 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -101,8 +101,6 @@ struct KernelCore::Impl {
101 101
102 current_process = nullptr; 102 current_process = nullptr;
103 103
104 system_resource_limit = nullptr;
105
106 global_handle_table.Clear(); 104 global_handle_table.Clear();
107 105
108 preemption_event = nullptr; 106 preemption_event = nullptr;
@@ -111,6 +109,13 @@ struct KernelCore::Impl {
111 109
112 exclusive_monitor.reset(); 110 exclusive_monitor.reset();
113 111
112 hid_shared_mem = nullptr;
113 font_shared_mem = nullptr;
114 irs_shared_mem = nullptr;
115 time_shared_mem = nullptr;
116
117 system_resource_limit = nullptr;
118
114 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others 119 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
115 next_host_thread_id = Core::Hardware::NUM_CPU_CORES; 120 next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
116 } 121 }
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 3ec0e1eca..615e20a54 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -508,7 +508,7 @@ public:
508 {1, &IManagerForApplication::GetAccountId, "GetAccountId"}, 508 {1, &IManagerForApplication::GetAccountId, "GetAccountId"},
509 {2, nullptr, "EnsureIdTokenCacheAsync"}, 509 {2, nullptr, "EnsureIdTokenCacheAsync"},
510 {3, nullptr, "LoadIdTokenCache"}, 510 {3, nullptr, "LoadIdTokenCache"},
511 {130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"}, 511 {130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"},
512 {150, nullptr, "CreateAuthorizationRequest"}, 512 {150, nullptr, "CreateAuthorizationRequest"},
513 {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"}, 513 {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"},
514 {170, nullptr, "LoadNetworkServiceLicenseKindAsync"}, 514 {170, nullptr, "LoadNetworkServiceLicenseKindAsync"},
@@ -534,6 +534,22 @@ private:
534 rb.PushRaw<u64>(user_id.GetNintendoID()); 534 rb.PushRaw<u64>(user_id.GetNintendoID());
535 } 535 }
536 536
537 void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) {
538 LOG_WARNING(Service_ACC, "(STUBBED) called");
539
540 std::vector<u8> nas_user_base_for_application(0x68);
541 ctx.WriteBuffer(nas_user_base_for_application, 0);
542
543 if (ctx.CanWriteBuffer(1)) {
544 std::vector<u8> unknown_out_buffer(ctx.GetWriteBufferSize(1));
545 ctx.WriteBuffer(unknown_out_buffer, 1);
546 }
547
548 IPC::ResponseBuilder rb{ctx, 4};
549 rb.Push(RESULT_SUCCESS);
550 rb.PushRaw<u64>(user_id.GetNintendoID());
551 }
552
537 void StoreOpenContext(Kernel::HLERequestContext& ctx) { 553 void StoreOpenContext(Kernel::HLERequestContext& ctx) {
538 LOG_WARNING(Service_ACC, "(STUBBED) called"); 554 LOG_WARNING(Service_ACC, "(STUBBED) called");
539 IPC::ResponseBuilder rb{ctx, 2}; 555 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ffc3dfdc3..ba27bbb05 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -273,8 +273,8 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
273 {204, &Hid::PermitVibration, "PermitVibration"}, 273 {204, &Hid::PermitVibration, "PermitVibration"},
274 {205, &Hid::IsVibrationPermitted, "IsVibrationPermitted"}, 274 {205, &Hid::IsVibrationPermitted, "IsVibrationPermitted"},
275 {206, &Hid::SendVibrationValues, "SendVibrationValues"}, 275 {206, &Hid::SendVibrationValues, "SendVibrationValues"},
276 {207, nullptr, "SendVibrationGcErmCommand"}, 276 {207, &Hid::SendVibrationGcErmCommand, "SendVibrationGcErmCommand"},
277 {208, nullptr, "GetActualVibrationGcErmCommand"}, 277 {208, &Hid::GetActualVibrationGcErmCommand, "GetActualVibrationGcErmCommand"},
278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, 278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, 279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, 280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
@@ -1093,7 +1093,22 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1093 1093
1094 VibrationDeviceInfo vibration_device_info; 1094 VibrationDeviceInfo vibration_device_info;
1095 1095
1096 vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; 1096 switch (vibration_device_handle.npad_type) {
1097 case Controller_NPad::NpadType::ProController:
1098 case Controller_NPad::NpadType::Handheld:
1099 case Controller_NPad::NpadType::JoyconDual:
1100 case Controller_NPad::NpadType::JoyconLeft:
1101 case Controller_NPad::NpadType::JoyconRight:
1102 default:
1103 vibration_device_info.type = VibrationDeviceType::LinearResonantActuator;
1104 break;
1105 case Controller_NPad::NpadType::GameCube:
1106 vibration_device_info.type = VibrationDeviceType::GcErm;
1107 break;
1108 case Controller_NPad::NpadType::Pokeball:
1109 vibration_device_info.type = VibrationDeviceType::Unknown;
1110 break;
1111 }
1097 1112
1098 switch (vibration_device_handle.device_index) { 1113 switch (vibration_device_handle.device_index) {
1099 case Controller_NPad::DeviceIndex::Left: 1114 case Controller_NPad::DeviceIndex::Left:
@@ -1215,6 +1230,108 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
1215 rb.Push(RESULT_SUCCESS); 1230 rb.Push(RESULT_SUCCESS);
1216} 1231}
1217 1232
1233void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1234 IPC::RequestParser rp{ctx};
1235 struct Parameters {
1236 Controller_NPad::DeviceHandle vibration_device_handle;
1237 u64 applet_resource_user_id;
1238 VibrationGcErmCommand gc_erm_command;
1239 };
1240 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1241
1242 const auto parameters{rp.PopRaw<Parameters>()};
1243
1244 /**
1245 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1246 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
1247 * in order to differentiate between Stop and StopHard commands.
1248 * This is done to reuse the controller vibration functions made for regular controllers.
1249 */
1250 const auto vibration_value = [parameters] {
1251 switch (parameters.gc_erm_command) {
1252 case VibrationGcErmCommand::Stop:
1253 return Controller_NPad::VibrationValue{
1254 .amp_low = 0.0f,
1255 .freq_low = 160.0f,
1256 .amp_high = 0.0f,
1257 .freq_high = 320.0f,
1258 };
1259 case VibrationGcErmCommand::Start:
1260 return Controller_NPad::VibrationValue{
1261 .amp_low = 1.0f,
1262 .freq_low = 160.0f,
1263 .amp_high = 1.0f,
1264 .freq_high = 320.0f,
1265 };
1266 case VibrationGcErmCommand::StopHard:
1267 return Controller_NPad::VibrationValue{
1268 .amp_low = 0.0f,
1269 .freq_low = 0.0f,
1270 .amp_high = 0.0f,
1271 .freq_high = 0.0f,
1272 };
1273 default:
1274 return Controller_NPad::DEFAULT_VIBRATION_VALUE;
1275 }
1276 }();
1277
1278 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1279 .VibrateController(parameters.vibration_device_handle, vibration_value);
1280
1281 LOG_DEBUG(Service_HID,
1282 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
1283 "gc_erm_command={}",
1284 parameters.vibration_device_handle.npad_type,
1285 parameters.vibration_device_handle.npad_id,
1286 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
1287 parameters.gc_erm_command);
1288
1289 IPC::ResponseBuilder rb{ctx, 2};
1290 rb.Push(RESULT_SUCCESS);
1291}
1292
1293void Hid::GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1294 IPC::RequestParser rp{ctx};
1295 struct Parameters {
1296 Controller_NPad::DeviceHandle vibration_device_handle;
1297 INSERT_PADDING_WORDS_NOINIT(1);
1298 u64 applet_resource_user_id;
1299 };
1300
1301 const auto parameters{rp.PopRaw<Parameters>()};
1302
1303 const auto last_vibration = applet_resource->GetController<Controller_NPad>(HidController::NPad)
1304 .GetLastVibration(parameters.vibration_device_handle);
1305
1306 const auto gc_erm_command = [last_vibration] {
1307 if (last_vibration.amp_low != 0.0f || last_vibration.amp_high != 0.0f) {
1308 return VibrationGcErmCommand::Start;
1309 }
1310
1311 /**
1312 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1313 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
1314 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
1315 * This is done to reuse the controller vibration functions made for regular controllers.
1316 */
1317 if (last_vibration.freq_low == 0.0f && last_vibration.freq_high == 0.0f) {
1318 return VibrationGcErmCommand::StopHard;
1319 }
1320
1321 return VibrationGcErmCommand::Stop;
1322 }();
1323
1324 LOG_DEBUG(Service_HID,
1325 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1326 parameters.vibration_device_handle.npad_type,
1327 parameters.vibration_device_handle.npad_id,
1328 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1329
1330 IPC::ResponseBuilder rb{ctx, 4};
1331 rb.Push(RESULT_SUCCESS);
1332 rb.PushEnum(gc_erm_command);
1333}
1334
1218void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { 1335void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
1219 IPC::RequestParser rp{ctx}; 1336 IPC::RequestParser rp{ctx};
1220 const auto applet_resource_user_id{rp.Pop<u64>()}; 1337 const auto applet_resource_user_id{rp.Pop<u64>()};
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 06ddcf3e4..36ed228c8 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -136,6 +136,8 @@ private:
136 void PermitVibration(Kernel::HLERequestContext& ctx); 136 void PermitVibration(Kernel::HLERequestContext& ctx);
137 void IsVibrationPermitted(Kernel::HLERequestContext& ctx); 137 void IsVibrationPermitted(Kernel::HLERequestContext& ctx);
138 void SendVibrationValues(Kernel::HLERequestContext& ctx); 138 void SendVibrationValues(Kernel::HLERequestContext& ctx);
139 void SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx);
140 void GetActualVibrationGcErmCommand(Kernel::HLERequestContext& ctx);
139 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); 141 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
140 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); 142 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
141 void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); 143 void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx);
@@ -154,7 +156,9 @@ private:
154 void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); 156 void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);
155 157
156 enum class VibrationDeviceType : u32 { 158 enum class VibrationDeviceType : u32 {
159 Unknown = 0,
157 LinearResonantActuator = 1, 160 LinearResonantActuator = 1,
161 GcErm = 2,
158 }; 162 };
159 163
160 enum class VibrationDevicePosition : u32 { 164 enum class VibrationDevicePosition : u32 {
@@ -163,6 +167,12 @@ private:
163 Right = 2, 167 Right = 2,
164 }; 168 };
165 169
170 enum class VibrationGcErmCommand : u64 {
171 Stop = 0,
172 Start = 1,
173 StopHard = 2,
174 };
175
166 struct VibrationDeviceInfo { 176 struct VibrationDeviceInfo {
167 VibrationDeviceType type{}; 177 VibrationDeviceType type{};
168 VibrationDevicePosition position{}; 178 VibrationDevicePosition position{};
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 858623e2b..1f7309f6b 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -279,6 +279,10 @@ const SharedMemory& TimeManager::GetSharedMemory() const {
279 return impl->shared_memory; 279 return impl->shared_memory;
280} 280}
281 281
282void TimeManager::Shutdown() {
283 impl.reset();
284}
285
282void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) { 286void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
283 impl->UpdateLocalSystemClockTime(system, posix_time); 287 impl->UpdateLocalSystemClockTime(system, posix_time);
284} 288}
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h
index 993c7c288..4db8cc0e1 100644
--- a/src/core/hle/service/time/time_manager.h
+++ b/src/core/hle/service/time/time_manager.h
@@ -61,6 +61,8 @@ public:
61 61
62 const SharedMemory& GetSharedMemory() const; 62 const SharedMemory& GetSharedMemory() const;
63 63
64 void Shutdown();
65
64 void SetupTimeZoneManager(std::string location_name, 66 void SetupTimeZoneManager(std::string location_name,
65 Clock::SteadyClockTimePoint time_zone_updated_time_point, 67 Clock::SteadyClockTimePoint time_zone_updated_time_point,
66 std::size_t total_location_name_count, u128 time_zone_rule_version, 68 std::size_t total_location_name_count, u128 time_zone_rule_version,
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 48d5c4a5e..1ae5f1d62 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -239,6 +239,7 @@ Device::Device() {
239 has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; 239 has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2;
240 has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; 240 has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory;
241 has_debugging_tool_attached = IsDebugToolAttached(extensions); 241 has_debugging_tool_attached = IsDebugToolAttached(extensions);
242 has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float");
242 243
243 // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive 244 // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive
244 // uniform buffers as "push constants" 245 // uniform buffers as "push constants"
@@ -275,6 +276,7 @@ Device::Device(std::nullptr_t) {
275 has_image_load_formatted = true; 276 has_image_load_formatted = true;
276 has_texture_shadow_lod = true; 277 has_texture_shadow_lod = true;
277 has_variable_aoffi = true; 278 has_variable_aoffi = true;
279 has_depth_buffer_float = true;
278} 280}
279 281
280bool Device::TestVariableAoffi() { 282bool Device::TestVariableAoffi() {
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index ee053776d..f24bd0c7b 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -122,6 +122,10 @@ public:
122 return use_driver_cache; 122 return use_driver_cache;
123 } 123 }
124 124
125 bool HasDepthBufferFloat() const {
126 return has_depth_buffer_float;
127 }
128
125private: 129private:
126 static bool TestVariableAoffi(); 130 static bool TestVariableAoffi();
127 static bool TestPreciseBug(); 131 static bool TestPreciseBug();
@@ -150,6 +154,7 @@ private:
150 bool use_assembly_shaders{}; 154 bool use_assembly_shaders{};
151 bool use_asynchronous_shaders{}; 155 bool use_asynchronous_shaders{};
152 bool use_driver_cache{}; 156 bool use_driver_cache{};
157 bool has_depth_buffer_float{};
153}; 158};
154 159
155} // namespace OpenGL 160} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 418644108..4610fd160 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -889,7 +889,11 @@ void RasterizerOpenGL::SyncViewport() {
889 const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; 889 const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
890 const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z; 890 const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
891 const GLdouble far_depth = src.translate_z + src.scale_z; 891 const GLdouble far_depth = src.translate_z + src.scale_z;
892 glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth); 892 if (device.HasDepthBufferFloat()) {
893 glDepthRangeIndexeddNV(static_cast<GLuint>(i), near_depth, far_depth);
894 } else {
895 glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth);
896 }
893 897
894 if (!GLAD_GL_NV_viewport_swizzle) { 898 if (!GLAD_GL_NV_viewport_swizzle) {
895 continue; 899 continue;
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 529570ff0..5cf7cd151 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -335,6 +335,10 @@ void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop
335 const VideoCore::DiskResourceLoadCallback& callback) { 335 const VideoCore::DiskResourceLoadCallback& callback) {
336 disk_cache.BindTitleID(title_id); 336 disk_cache.BindTitleID(title_id);
337 const std::optional transferable = disk_cache.LoadTransferable(); 337 const std::optional transferable = disk_cache.LoadTransferable();
338
339 LOG_INFO(Render_OpenGL, "Total Shader Count: {}",
340 transferable.has_value() ? transferable->size() : 0);
341
338 if (!transferable) { 342 if (!transferable) {
339 return; 343 return;
340 } 344 }
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 848eedd66..668633e7b 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -201,10 +201,6 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer,
201 }); 201 });
202} 202}
203 203
204void BufferCacheRuntime::BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
205 update_descriptor_queue.AddBuffer(buffer, offset, size);
206}
207
208void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle) { 204void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle) {
209 if (num_indices <= current_num_indices) { 205 if (num_indices <= current_num_indices) {
210 return; 206 return;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 041e6515c..982e92191 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -8,6 +8,7 @@
8#include "video_core/engines/maxwell_3d.h" 8#include "video_core/engines/maxwell_3d.h"
9#include "video_core/renderer_vulkan/vk_compute_pass.h" 9#include "video_core/renderer_vulkan/vk_compute_pass.h"
10#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" 10#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
11#include "video_core/renderer_vulkan/vk_update_descriptor.h"
11#include "video_core/vulkan_common/vulkan_memory_allocator.h" 12#include "video_core/vulkan_common/vulkan_memory_allocator.h"
12#include "video_core/vulkan_common/vulkan_wrapper.h" 13#include "video_core/vulkan_common/vulkan_wrapper.h"
13 14
@@ -16,7 +17,6 @@ namespace Vulkan {
16class Device; 17class Device;
17class VKDescriptorPool; 18class VKDescriptorPool;
18class VKScheduler; 19class VKScheduler;
19class VKUpdateDescriptorQueue;
20 20
21class BufferCacheRuntime; 21class BufferCacheRuntime;
22 22
@@ -86,7 +86,9 @@ public:
86 } 86 }
87 87
88private: 88private:
89 void BindBuffer(VkBuffer buffer, u32 offset, u32 size); 89 void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
90 update_descriptor_queue.AddBuffer(buffer, offset, size);
91 }
90 92
91 void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle); 93 void ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle);
92 94
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 40e2e0d38..c6846d886 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1845,13 +1845,21 @@ private:
1845 1845
1846 Expression TextureGather(Operation operation) { 1846 Expression TextureGather(Operation operation) {
1847 const auto& meta = std::get<MetaTexture>(operation.GetMeta()); 1847 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
1848 UNIMPLEMENTED_IF(!meta.aoffi.empty());
1849 1848
1850 const Id coords = GetCoordinates(operation, Type::Float); 1849 const Id coords = GetCoordinates(operation, Type::Float);
1850
1851 spv::ImageOperandsMask mask = spv::ImageOperandsMask::MaskNone;
1852 std::vector<Id> operands;
1851 Id texture{}; 1853 Id texture{};
1854
1855 if (!meta.aoffi.empty()) {
1856 mask = mask | spv::ImageOperandsMask::Offset;
1857 operands.push_back(GetOffsetCoordinates(operation));
1858 }
1859
1852 if (meta.sampler.is_shadow) { 1860 if (meta.sampler.is_shadow) {
1853 texture = OpImageDrefGather(t_float4, GetTextureSampler(operation), coords, 1861 texture = OpImageDrefGather(t_float4, GetTextureSampler(operation), coords,
1854 AsFloat(Visit(meta.depth_compare))); 1862 AsFloat(Visit(meta.depth_compare)), mask, operands);
1855 } else { 1863 } else {
1856 u32 component_value = 0; 1864 u32 component_value = 0;
1857 if (meta.component) { 1865 if (meta.component) {
@@ -1860,7 +1868,7 @@ private:
1860 component_value = component->GetValue(); 1868 component_value = component->GetValue();
1861 } 1869 }
1862 texture = OpImageGather(t_float4, GetTextureSampler(operation), coords, 1870 texture = OpImageGather(t_float4, GetTextureSampler(operation), coords,
1863 Constant(t_uint, component_value)); 1871 Constant(t_uint, component_value), mask, operands);
1864 } 1872 }
1865 return GetTextureElement(operation, texture, Type::Float); 1873 return GetTextureElement(operation, texture, Type::Float);
1866 } 1874 }
@@ -1928,13 +1936,22 @@ private:
1928 1936
1929 const Id image = GetTextureImage(operation); 1937 const Id image = GetTextureImage(operation);
1930 const Id coords = GetCoordinates(operation, Type::Int); 1938 const Id coords = GetCoordinates(operation, Type::Int);
1939
1940 spv::ImageOperandsMask mask = spv::ImageOperandsMask::MaskNone;
1941 std::vector<Id> operands;
1931 Id fetch; 1942 Id fetch;
1943
1932 if (meta.lod && !meta.sampler.is_buffer) { 1944 if (meta.lod && !meta.sampler.is_buffer) {
1933 fetch = OpImageFetch(t_float4, image, coords, spv::ImageOperandsMask::Lod, 1945 mask = mask | spv::ImageOperandsMask::Lod;
1934 AsInt(Visit(meta.lod))); 1946 operands.push_back(AsInt(Visit(meta.lod)));
1935 } else { 1947 }
1936 fetch = OpImageFetch(t_float4, image, coords); 1948
1949 if (!meta.aoffi.empty()) {
1950 mask = mask | spv::ImageOperandsMask::Offset;
1951 operands.push_back(GetOffsetCoordinates(operation));
1937 } 1952 }
1953
1954 fetch = OpImageFetch(t_float4, image, coords, mask, operands);
1938 return GetTextureElement(operation, fetch, Type::Float); 1955 return GetTextureElement(operation, fetch, Type::Float);
1939 } 1956 }
1940 1957
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
index f99273c6a..dc45fdcb1 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
@@ -20,20 +20,20 @@ VKUpdateDescriptorQueue::VKUpdateDescriptorQueue(const Device& device_, VKSchedu
20VKUpdateDescriptorQueue::~VKUpdateDescriptorQueue() = default; 20VKUpdateDescriptorQueue::~VKUpdateDescriptorQueue() = default;
21 21
22void VKUpdateDescriptorQueue::TickFrame() { 22void VKUpdateDescriptorQueue::TickFrame() {
23 payload.clear(); 23 payload_cursor = payload.data();
24} 24}
25 25
26void VKUpdateDescriptorQueue::Acquire() { 26void VKUpdateDescriptorQueue::Acquire() {
27 // Minimum number of entries required. 27 // Minimum number of entries required.
28 // This is the maximum number of entries a single draw call migth use. 28 // This is the maximum number of entries a single draw call migth use.
29 static constexpr std::size_t MIN_ENTRIES = 0x400; 29 static constexpr size_t MIN_ENTRIES = 0x400;
30 30
31 if (payload.size() + MIN_ENTRIES >= payload.max_size()) { 31 if (std::distance(payload.data(), payload_cursor) + MIN_ENTRIES >= payload.max_size()) {
32 LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread"); 32 LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread");
33 scheduler.WaitWorker(); 33 scheduler.WaitWorker();
34 payload.clear(); 34 payload_cursor = payload.data();
35 } 35 }
36 upload_start = &*payload.end(); 36 upload_start = payload_cursor;
37} 37}
38 38
39void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, 39void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h
index e214f7195..d35e77c44 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.h
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h
@@ -4,8 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <variant> 7#include <array>
8#include <boost/container/static_vector.hpp>
9 8
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "video_core/vulkan_common/vulkan_wrapper.h" 10#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -16,13 +15,15 @@ class Device;
16class VKScheduler; 15class VKScheduler;
17 16
18struct DescriptorUpdateEntry { 17struct DescriptorUpdateEntry {
19 DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {} 18 struct Empty {};
20 19
20 DescriptorUpdateEntry() = default;
21 DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {}
21 DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {} 22 DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {}
22
23 DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {} 23 DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {}
24 24
25 union { 25 union {
26 Empty empty{};
26 VkDescriptorImageInfo image; 27 VkDescriptorImageInfo image;
27 VkDescriptorBufferInfo buffer; 28 VkDescriptorBufferInfo buffer;
28 VkBufferView texel_buffer; 29 VkBufferView texel_buffer;
@@ -41,39 +42,40 @@ public:
41 void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); 42 void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set);
42 43
43 void AddSampledImage(VkImageView image_view, VkSampler sampler) { 44 void AddSampledImage(VkImageView image_view, VkSampler sampler) {
44 payload.emplace_back(VkDescriptorImageInfo{ 45 *(payload_cursor++) = VkDescriptorImageInfo{
45 .sampler = sampler, 46 .sampler = sampler,
46 .imageView = image_view, 47 .imageView = image_view,
47 .imageLayout = VK_IMAGE_LAYOUT_GENERAL, 48 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
48 }); 49 };
49 } 50 }
50 51
51 void AddImage(VkImageView image_view) { 52 void AddImage(VkImageView image_view) {
52 payload.emplace_back(VkDescriptorImageInfo{ 53 *(payload_cursor++) = VkDescriptorImageInfo{
53 .sampler = VK_NULL_HANDLE, 54 .sampler = VK_NULL_HANDLE,
54 .imageView = image_view, 55 .imageView = image_view,
55 .imageLayout = VK_IMAGE_LAYOUT_GENERAL, 56 .imageLayout = VK_IMAGE_LAYOUT_GENERAL,
56 }); 57 };
57 } 58 }
58 59
59 void AddBuffer(VkBuffer buffer, u64 offset, size_t size) { 60 void AddBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size) {
60 payload.emplace_back(VkDescriptorBufferInfo{ 61 *(payload_cursor++) = VkDescriptorBufferInfo{
61 .buffer = buffer, 62 .buffer = buffer,
62 .offset = offset, 63 .offset = offset,
63 .range = size, 64 .range = size,
64 }); 65 };
65 } 66 }
66 67
67 void AddTexelBuffer(VkBufferView texel_buffer) { 68 void AddTexelBuffer(VkBufferView texel_buffer) {
68 payload.emplace_back(texel_buffer); 69 *(payload_cursor++) = texel_buffer;
69 } 70 }
70 71
71private: 72private:
72 const Device& device; 73 const Device& device;
73 VKScheduler& scheduler; 74 VKScheduler& scheduler;
74 75
76 DescriptorUpdateEntry* payload_cursor = nullptr;
75 const DescriptorUpdateEntry* upload_start = nullptr; 77 const DescriptorUpdateEntry* upload_start = nullptr;
76 boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload; 78 std::array<DescriptorUpdateEntry, 0x10000> payload;
77}; 79};
78 80
79} // namespace Vulkan 81} // namespace Vulkan
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index 50f4e7d35..7728f600e 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -330,6 +330,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
330 case StoreType::Bits32: 330 case StoreType::Bits32:
331 (this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0)); 331 (this->*set_memory)(bb, GetAddress(0), GetRegister(instr.gpr0));
332 break; 332 break;
333 case StoreType::Unsigned16:
333 case StoreType::Signed16: { 334 case StoreType::Signed16: {
334 Node address = GetAddress(0); 335 Node address = GetAddress(0);
335 Node memory = (this->*get_memory)(address); 336 Node memory = (this->*get_memory)(address);
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 833fa2a39..c69681e8d 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -806,6 +806,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
806 806
807 const std::size_t type_coord_count = GetCoordCount(texture_type); 807 const std::size_t type_coord_count = GetCoordCount(texture_type);
808 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; 808 const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL;
809 const bool aoffi_enabled = instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI);
809 810
810 // If enabled arrays index is always stored in the gpr8 field 811 // If enabled arrays index is always stored in the gpr8 field
811 const u64 array_register = instr.gpr8.Value(); 812 const u64 array_register = instr.gpr8.Value();
@@ -820,17 +821,23 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is
820 std::vector<Node> coords; 821 std::vector<Node> coords;
821 for (std::size_t i = 0; i < type_coord_count; ++i) { 822 for (std::size_t i = 0; i < type_coord_count; ++i) {
822 const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1); 823 const bool last = (i == (type_coord_count - 1)) && (type_coord_count > 1);
823 coords.push_back(GetRegister(last ? last_coord_register : coord_register + i)); 824 coords.push_back(
825 GetRegister(last && !aoffi_enabled ? last_coord_register : coord_register + i));
824 } 826 }
825 827
826 const Node array = is_array ? GetRegister(array_register) : nullptr; 828 const Node array = is_array ? GetRegister(array_register) : nullptr;
827 // When lod is used always is in gpr20 829 // When lod is used always is in gpr20
828 const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0); 830 const Node lod = lod_enabled ? GetRegister(instr.gpr20) : Immediate(0);
829 831
832 std::vector<Node> aoffi;
833 if (aoffi_enabled) {
834 aoffi = GetAoffiCoordinates(GetRegister(instr.gpr20), type_coord_count, false);
835 }
836
830 Node4 values; 837 Node4 values;
831 for (u32 element = 0; element < values.size(); ++element) { 838 for (u32 element = 0; element < values.size(); ++element) {
832 auto coords_copy = coords; 839 auto coords_copy = coords;
833 MetaTexture meta{*sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}}; 840 MetaTexture meta{*sampler, array, {}, aoffi, {}, {}, {}, lod, {}, element, {}};
834 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); 841 values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy));
835 } 842 }
836 return values; 843 return values;