Compare commits
13 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bd9a4456c | ||
|
|
58a4c86797 | ||
|
|
35a77c3bb2 | ||
|
|
c1016b68ae | ||
|
|
b30df50076 | ||
|
|
5afe1367ba | ||
|
|
24700af3c2 | ||
|
|
f9ef721ca6 | ||
|
|
c34ed4bbd8 | ||
|
|
7351884588 | ||
|
|
8b98c4e5a0 | ||
|
|
7d8f748696 | ||
|
|
bdd96118d1 |
@@ -289,6 +289,19 @@ enum class GyroscopeZeroDriftMode : u32 {
|
||||
Tight = 2,
|
||||
};
|
||||
|
||||
// This is nn::settings::system::TouchScreenMode
|
||||
enum class TouchScreenMode : u32 {
|
||||
Stylus = 0,
|
||||
Standard = 1,
|
||||
};
|
||||
|
||||
// This is nn::hid::TouchScreenModeForNx
|
||||
enum class TouchScreenModeForNx : u8 {
|
||||
UseSystemSetting,
|
||||
Finger,
|
||||
Heat2,
|
||||
};
|
||||
|
||||
// This is nn::hid::NpadStyleTag
|
||||
struct NpadStyleTag {
|
||||
union {
|
||||
@@ -334,6 +347,14 @@ struct TouchState {
|
||||
};
|
||||
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
||||
|
||||
// This is nn::hid::TouchScreenConfigurationForNx
|
||||
struct TouchScreenConfigurationForNx {
|
||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||
INSERT_PADDING_BYTES(0xF);
|
||||
};
|
||||
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10,
|
||||
"TouchScreenConfigurationForNx is an invalid size");
|
||||
|
||||
struct NpadColor {
|
||||
u8 r{};
|
||||
u8 g{};
|
||||
@@ -662,6 +683,11 @@ struct MouseState {
|
||||
};
|
||||
static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
|
||||
|
||||
struct UniquePadId {
|
||||
u64 id;
|
||||
};
|
||||
static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
|
||||
|
||||
/// Converts a NpadIdType to an array index.
|
||||
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
||||
switch (npad_id_type) {
|
||||
|
||||
@@ -19,13 +19,7 @@ public:
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
s64 GetCount() const {
|
||||
return GetTick();
|
||||
}
|
||||
|
||||
void RegisterTask(KTimerTask* task, s64 time_from_now) {
|
||||
this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
|
||||
}
|
||||
s64 GetTick() const;
|
||||
|
||||
void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
|
||||
KScopedDisableDispatch dd{m_kernel};
|
||||
@@ -42,7 +36,6 @@ private:
|
||||
void EnableInterrupt(s64 wakeup_time);
|
||||
void DisableInterrupt();
|
||||
bool GetInterruptEnabled();
|
||||
s64 GetTick() const;
|
||||
void DoTask();
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "common/overflow.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
|
||||
@@ -15,9 +16,7 @@ KResourceLimit::KResourceLimit(KernelCore& kernel)
|
||||
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {}
|
||||
KResourceLimit::~KResourceLimit() = default;
|
||||
|
||||
void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) {
|
||||
m_core_timing = core_timing;
|
||||
}
|
||||
void KResourceLimit::Initialize() {}
|
||||
|
||||
void KResourceLimit::Finalize() {}
|
||||
|
||||
@@ -86,7 +85,7 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
||||
}
|
||||
|
||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
|
||||
return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout);
|
||||
return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout);
|
||||
}
|
||||
|
||||
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||
@@ -117,7 +116,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
|
||||
}
|
||||
|
||||
if (m_current_hints[index] + value <= m_limit_values[index] &&
|
||||
(timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) {
|
||||
(timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) {
|
||||
m_waiter_count++;
|
||||
m_cond_var.Wait(std::addressof(m_lock), timeout, false);
|
||||
m_waiter_count--;
|
||||
@@ -154,7 +153,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
|
||||
|
||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
|
||||
auto* resource_limit = KResourceLimit::Create(system.Kernel());
|
||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
||||
resource_limit->Initialize();
|
||||
|
||||
// Initialize default resource limit values.
|
||||
// TODO(bunnei): These values are the system defaults, the limits for service processes are
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
explicit KResourceLimit(KernelCore& kernel);
|
||||
~KResourceLimit() override;
|
||||
|
||||
void Initialize(const Core::Timing::CoreTiming* core_timing);
|
||||
void Initialize();
|
||||
void Finalize() override;
|
||||
|
||||
s64 GetLimitValue(LimitableResource which) const;
|
||||
@@ -57,7 +57,6 @@ private:
|
||||
mutable KLightLock m_lock;
|
||||
s32 m_waiter_count{};
|
||||
KLightConditionVariable m_cond_var;
|
||||
const Core::Timing::CoreTiming* m_core_timing{};
|
||||
};
|
||||
|
||||
KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
~KScopedSchedulerLockAndSleep() {
|
||||
// Register the sleep.
|
||||
if (m_timeout_tick > 0) {
|
||||
m_timer->RegisterTask(m_thread, m_timeout_tick);
|
||||
m_timer->RegisterAbsoluteTask(m_thread, m_timeout_tick);
|
||||
}
|
||||
|
||||
// Unlock the scheduler.
|
||||
|
||||
@@ -231,7 +231,7 @@ struct KernelCore::Impl {
|
||||
void InitializeSystemResourceLimit(KernelCore& kernel,
|
||||
const Core::Timing::CoreTiming& core_timing) {
|
||||
system_resource_limit = KResourceLimit::Create(system.Kernel());
|
||||
system_resource_limit->Initialize(&core_timing);
|
||||
system_resource_limit->Initialize();
|
||||
KResourceLimit::Register(kernel, system_resource_limit);
|
||||
|
||||
const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@@ -52,7 +53,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = offset_tick + 2;
|
||||
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_memory_layout.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
@@ -25,7 +26,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = offset_tick + 2;
|
||||
timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_client_session.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_server_session.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@@ -82,12 +83,29 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
|
||||
R_TRY(session->SendReply());
|
||||
}
|
||||
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||
s64 timeout;
|
||||
if (timeout_ns > 0) {
|
||||
const s64 offset_tick(timeout_ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = timeout_ns;
|
||||
}
|
||||
|
||||
// Wait for a message.
|
||||
while (true) {
|
||||
// Wait for an object.
|
||||
s32 index;
|
||||
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
|
||||
num_handles, timeout_ns);
|
||||
num_handles, timeout);
|
||||
if (result == ResultTimedOut) {
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
|
||||
SCOPE_EXIT({ resource_limit->Close(); });
|
||||
|
||||
// Initialize the resource limit.
|
||||
resource_limit->Initialize(std::addressof(system.CoreTiming()));
|
||||
resource_limit->Initialize();
|
||||
|
||||
// Register the limit.
|
||||
KResourceLimit::Register(kernel, resource_limit);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
@@ -83,9 +84,20 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
||||
}
|
||||
});
|
||||
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
s64 timeout;
|
||||
if (timeout_ns > 0) {
|
||||
u64 ticks = kernel.HardwareTimer().GetTick();
|
||||
ticks += timeout_ns;
|
||||
ticks += 2;
|
||||
|
||||
timeout = ticks;
|
||||
} else {
|
||||
timeout = timeout_ns;
|
||||
}
|
||||
|
||||
// Wait on the objects.
|
||||
Result res =
|
||||
KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);
|
||||
Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout);
|
||||
|
||||
R_SUCCEED_IF(res == ResultSessionClosed);
|
||||
R_RETURN(res);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_hardware_timer.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
@@ -42,9 +43,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
|
||||
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
|
||||
|
||||
// Reserve a new thread from the process resource limit (waiting up to 100ms).
|
||||
KScopedResourceReservation thread_reservation(
|
||||
std::addressof(process), LimitableResource::ThreadCountMax, 1,
|
||||
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
|
||||
KScopedResourceReservation thread_reservation(std::addressof(process),
|
||||
LimitableResource::ThreadCountMax, 1,
|
||||
kernel.HardwareTimer().GetTick() + 100000000);
|
||||
R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
|
||||
|
||||
// Create the thread.
|
||||
@@ -102,20 +103,31 @@ void ExitThread(Core::System& system) {
|
||||
}
|
||||
|
||||
/// Sleep the current thread
|
||||
void SleepThread(Core::System& system, s64 nanoseconds) {
|
||||
void SleepThread(Core::System& system, s64 ns) {
|
||||
auto& kernel = system.Kernel();
|
||||
const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
|
||||
const auto yield_type = static_cast<Svc::YieldType>(ns);
|
||||
|
||||
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
|
||||
LOG_TRACE(Kernel_SVC, "called nanoseconds={}", ns);
|
||||
|
||||
// When the input tick is positive, sleep.
|
||||
if (nanoseconds > 0) {
|
||||
if (ns > 0) {
|
||||
// Convert the timeout from nanoseconds to ticks.
|
||||
// NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
|
||||
s64 timeout;
|
||||
|
||||
const s64 offset_tick(ns);
|
||||
if (offset_tick > 0) {
|
||||
timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2;
|
||||
if (timeout <= 0) {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
} else {
|
||||
timeout = std::numeric_limits<s64>::max();
|
||||
}
|
||||
|
||||
// Sleep.
|
||||
// NOTE: Nintendo does not check the result of this sleep.
|
||||
static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
|
||||
static_cast<void>(GetCurrentThread(kernel).Sleep(timeout));
|
||||
} else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
|
||||
KScheduler::YieldWithoutCoreMigration(kernel);
|
||||
} else if (yield_type == Svc::YieldType::WithCoreMigration) {
|
||||
@@ -124,7 +136,6 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
|
||||
KScheduler::YieldToAnyThread(kernel);
|
||||
} else {
|
||||
// Nintendo does nothing at all if an otherwise invalid value is passed.
|
||||
ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,22 +16,6 @@ class EmulatedConsole;
|
||||
namespace Service::HID {
|
||||
class Controller_Touchscreen final : public ControllerBase {
|
||||
public:
|
||||
// This is nn::hid::TouchScreenModeForNx
|
||||
enum class TouchScreenModeForNx : u8 {
|
||||
UseSystemSetting,
|
||||
Finger,
|
||||
Heat2,
|
||||
};
|
||||
|
||||
// This is nn::hid::TouchScreenConfigurationForNx
|
||||
struct TouchScreenConfigurationForNx {
|
||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||
INSERT_PADDING_BYTES_NOINIT(0x7);
|
||||
INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
|
||||
};
|
||||
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
|
||||
"TouchScreenConfigurationForNx is an invalid size");
|
||||
|
||||
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
||||
~Controller_Touchscreen() override;
|
||||
|
||||
|
||||
@@ -2368,7 +2368,7 @@ void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
|
||||
|
||||
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()};
|
||||
const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
|
||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
||||
@@ -2543,7 +2543,8 @@ public:
|
||||
|
||||
class HidSys final : public ServiceFramework<HidSys> {
|
||||
public:
|
||||
explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} {
|
||||
explicit HidSys(Core::System& system_)
|
||||
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
||||
@@ -2568,7 +2569,7 @@ public:
|
||||
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
||||
{306, nullptr, "GetLastActiveNpad"},
|
||||
{306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
|
||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
||||
@@ -2624,7 +2625,7 @@ public:
|
||||
{700, nullptr, "ActivateUniquePad"},
|
||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
||||
{703, nullptr, "GetUniquePadIds"},
|
||||
{751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||
{751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
||||
@@ -2650,7 +2651,7 @@ public:
|
||||
{830, nullptr, "SetNotificationLedPattern"},
|
||||
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
||||
{832, nullptr, "PrepareHidsForNotificationWake"},
|
||||
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
|
||||
{850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
|
||||
{851, nullptr, "EnableUsbFullKeyController"},
|
||||
{852, nullptr, "IsUsbConnected"},
|
||||
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
||||
@@ -2682,7 +2683,7 @@ public:
|
||||
{1150, nullptr, "SetTouchScreenMagnification"},
|
||||
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
||||
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
||||
{1153, nullptr, "GetTouchScreenDefaultConfiguration"},
|
||||
{1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
|
||||
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
||||
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
||||
@@ -2749,6 +2750,8 @@ public:
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -2760,17 +2763,66 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetLastActiveNpad(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(Core::HID::NpadIdType::Handheld);
|
||||
}
|
||||
|
||||
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||
|
||||
const s64 total_entries = 0;
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
|
||||
|
||||
const std::vector<Core::HID::UniquePadId> unique_pads{};
|
||||
|
||||
ctx.WriteBuffer(unique_pads);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(total_entries);
|
||||
rb.Push(static_cast<u32>(unique_pads.size()));
|
||||
}
|
||||
|
||||
void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
|
||||
}
|
||||
|
||||
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
|
||||
const bool is_enabled = false;
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_enabled);
|
||||
}
|
||||
|
||||
void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called");
|
||||
|
||||
Core::HID::TouchScreenConfigurationForNx touchscreen_config{
|
||||
.mode = Core::HID::TouchScreenModeForNx::Finger,
|
||||
};
|
||||
|
||||
if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
|
||||
touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
|
||||
touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(touchscreen_config);
|
||||
}
|
||||
|
||||
Kernel::KEvent* joy_detach_event;
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
|
||||
@@ -449,6 +449,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
|
||||
case NativeWindowScalingMode::ScaleToWindow:
|
||||
case NativeWindowScalingMode::ScaleCrop:
|
||||
case NativeWindowScalingMode::NoScaleCrop:
|
||||
case NativeWindowScalingMode::PreserveAspectRatio:
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode);
|
||||
|
||||
@@ -41,6 +41,7 @@ enum class NativeWindowScalingMode : s32 {
|
||||
ScaleToWindow = 1,
|
||||
ScaleCrop = 2,
|
||||
NoScaleCrop = 3,
|
||||
PreserveAspectRatio = 4,
|
||||
};
|
||||
|
||||
/// Transform parameter for QueueBuffer
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
|
||||
Result DoHandshake() override {
|
||||
OSStatus status = SSLHandshake(context);
|
||||
return HandleReturn("SSLHandshake", 0, status).Code();
|
||||
return HandleReturn("SSLHandshake", 0, status);
|
||||
}
|
||||
|
||||
Result Read(size_t* out_size, std::span<u8> data) override {
|
||||
|
||||
@@ -220,7 +220,8 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
||||
ASSERT(num_textures <= MAX_TEXTURES);
|
||||
ASSERT(num_images <= MAX_IMAGES);
|
||||
|
||||
const bool assembly_shaders{assembly_programs[0].handle != 0};
|
||||
const auto backend = device.GetShaderBackend();
|
||||
const bool assembly_shaders{backend == Settings::ShaderBackend::Glasm};
|
||||
use_storage_buffers =
|
||||
!assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks();
|
||||
writes_global_memory &= !use_storage_buffers;
|
||||
@@ -230,7 +231,6 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
||||
GenerateTransformFeedbackState();
|
||||
}
|
||||
const bool in_parallel = thread_worker != nullptr;
|
||||
const auto backend = device.GetShaderBackend();
|
||||
auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
|
||||
shader_notify, backend, in_parallel,
|
||||
force_context_flush](ShaderContext::Context*) mutable {
|
||||
@@ -559,15 +559,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||
}
|
||||
|
||||
void GraphicsPipeline::ConfigureTransformFeedbackImpl() const {
|
||||
glTransformFeedbackStreamAttribsNV(num_xfb_attribs, xfb_attribs.data(), num_xfb_strides,
|
||||
xfb_streams.data(), GL_INTERLEAVED_ATTRIBS);
|
||||
glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), GL_SEPARATE_ATTRIBS);
|
||||
}
|
||||
|
||||
void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||
// TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal
|
||||
// when this is required.
|
||||
GLint* cursor{xfb_attribs.data()};
|
||||
GLint* current_stream{xfb_streams.data()};
|
||||
|
||||
for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) {
|
||||
const auto& layout = key.xfb_state.layouts[feedback];
|
||||
@@ -575,15 +573,6 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||
if (layout.varying_count == 0) {
|
||||
continue;
|
||||
}
|
||||
*current_stream = static_cast<GLint>(feedback);
|
||||
if (current_stream != xfb_streams.data()) {
|
||||
// When stepping one stream, push the expected token
|
||||
cursor[0] = GL_NEXT_BUFFER_NV;
|
||||
cursor[1] = 0;
|
||||
cursor[2] = 0;
|
||||
cursor += XFB_ENTRY_STRIDE;
|
||||
}
|
||||
++current_stream;
|
||||
|
||||
const auto& locations = key.xfb_state.varyings[feedback];
|
||||
std::optional<u32> current_index;
|
||||
@@ -619,7 +608,6 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||
}
|
||||
}
|
||||
num_xfb_attribs = static_cast<GLsizei>((cursor - xfb_attribs.data()) / XFB_ENTRY_STRIDE);
|
||||
num_xfb_strides = static_cast<GLsizei>(current_stream - xfb_streams.data());
|
||||
}
|
||||
|
||||
void GraphicsPipeline::WaitForBuild() {
|
||||
|
||||
@@ -154,9 +154,7 @@ private:
|
||||
|
||||
static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
|
||||
GLsizei num_xfb_attribs{};
|
||||
GLsizei num_xfb_strides{};
|
||||
std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{};
|
||||
std::array<GLint, Maxwell::NumTransformFeedbackBuffers> xfb_streams{};
|
||||
|
||||
std::mutex built_mutex;
|
||||
std::condition_variable built_condvar;
|
||||
|
||||
@@ -1335,8 +1335,7 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
|
||||
}
|
||||
const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
|
||||
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
|
||||
const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
|
||||
: VideoCommon::ObtainBufferOperation::MarkAsWritten;
|
||||
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing;
|
||||
const auto [buffer, offset] =
|
||||
buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
|
||||
|
||||
@@ -1345,12 +1344,8 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
|
||||
const std::span copy_span{©, 1};
|
||||
|
||||
if constexpr (IS_IMAGE_UPLOAD) {
|
||||
texture_cache.PrepareImage(image_id, true, false);
|
||||
image->UploadMemory(buffer->Handle(), offset, copy_span);
|
||||
} else {
|
||||
if (offset % BytesPerBlock(image->info.format)) {
|
||||
return false;
|
||||
}
|
||||
texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
|
||||
buffer_operand.address, buffer_size);
|
||||
}
|
||||
|
||||
@@ -830,8 +830,7 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
|
||||
}
|
||||
const u32 buffer_size = static_cast<u32>(buffer_operand.pitch * buffer_operand.height);
|
||||
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
|
||||
const auto post_op = IS_IMAGE_UPLOAD ? VideoCommon::ObtainBufferOperation::DoNothing
|
||||
: VideoCommon::ObtainBufferOperation::MarkAsWritten;
|
||||
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing;
|
||||
const auto [buffer, offset] =
|
||||
buffer_cache.ObtainBuffer(buffer_operand.address, buffer_size, sync_info, post_op);
|
||||
|
||||
@@ -840,12 +839,8 @@ bool AccelerateDMA::DmaBufferImageCopy(const Tegra::DMA::ImageCopy& copy_info,
|
||||
const std::span copy_span{©, 1};
|
||||
|
||||
if constexpr (IS_IMAGE_UPLOAD) {
|
||||
texture_cache.PrepareImage(image_id, true, false);
|
||||
image->UploadMemory(buffer->Handle(), offset, copy_span);
|
||||
} else {
|
||||
if (offset % BytesPerBlock(image->info.format)) {
|
||||
return false;
|
||||
}
|
||||
texture_cache.DownloadImageIntoBuffer(image, buffer->Handle(), offset, copy_span,
|
||||
buffer_operand.address, buffer_size);
|
||||
}
|
||||
|
||||
@@ -243,9 +243,6 @@ public:
|
||||
/// Create channel state.
|
||||
void CreateChannel(Tegra::Control::ChannelState& channel) final override;
|
||||
|
||||
/// Prepare an image to be used
|
||||
void PrepareImage(ImageId image_id, bool is_modification, bool invalidate);
|
||||
|
||||
std::recursive_mutex mutex;
|
||||
|
||||
private:
|
||||
@@ -390,6 +387,9 @@ private:
|
||||
/// Synchronize image aliases, copying data if needed
|
||||
void SynchronizeAliases(ImageId image_id);
|
||||
|
||||
/// Prepare an image to be used
|
||||
void PrepareImage(ImageId image_id, bool is_modification, bool invalidate);
|
||||
|
||||
/// Prepare an image view to be used
|
||||
void PrepareImageView(ImageViewId image_view_id, bool is_modification, bool invalidate);
|
||||
|
||||
|
||||
@@ -326,6 +326,43 @@ std::vector<const char*> ExtensionListForVulkan(
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
void Device::RemoveExtension(bool& extension, const std::string& extension_name) {
|
||||
extension = false;
|
||||
loaded_extensions.erase(extension_name);
|
||||
}
|
||||
|
||||
void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
|
||||
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
||||
LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
|
||||
this->RemoveExtension(is_suitable, extension_name);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Feature>
|
||||
void Device::RemoveExtensionFeature(bool& extension, Feature& feature,
|
||||
const std::string& extension_name) {
|
||||
// Unload extension.
|
||||
this->RemoveExtension(extension, extension_name);
|
||||
|
||||
// Save sType and pNext for chain.
|
||||
VkStructureType sType = feature.sType;
|
||||
void* pNext = feature.pNext;
|
||||
|
||||
// Clear feature struct and restore chain.
|
||||
feature = {};
|
||||
feature.sType = sType;
|
||||
feature.pNext = pNext;
|
||||
}
|
||||
|
||||
template <typename Feature>
|
||||
void Device::RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
|
||||
const std::string& extension_name) {
|
||||
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
||||
LOG_WARNING(Render_Vulkan, "Removing features for unsuitable extension {}", extension_name);
|
||||
this->RemoveExtensionFeature(is_suitable, feature, extension_name);
|
||||
}
|
||||
}
|
||||
|
||||
Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
|
||||
const vk::InstanceDispatch& dld_)
|
||||
: instance{instance_}, dld{dld_}, physical{physical_},
|
||||
@@ -397,21 +434,20 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (is_qualcomm || is_turnip) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
|
||||
extensions.custom_border_color = false;
|
||||
loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
|
||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (is_qualcomm) {
|
||||
must_emulate_scaled_formats = true;
|
||||
|
||||
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state");
|
||||
extensions.extended_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
||||
extensions.push_descriptor = false;
|
||||
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
// Patch the driver to enable BCn textures.
|
||||
@@ -440,15 +476,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
must_emulate_scaled_formats = true;
|
||||
|
||||
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state");
|
||||
extensions.extended_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
|
||||
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2");
|
||||
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||
extensions.extended_dynamic_state2 = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (is_nvidia) {
|
||||
@@ -464,8 +497,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
case NvidiaArchitecture::VoltaOrOlder:
|
||||
if (nv_major_version < 527) {
|
||||
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
|
||||
extensions.push_descriptor = false;
|
||||
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -480,8 +512,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
|
||||
extensions.extended_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state,
|
||||
features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state2 && is_radv) {
|
||||
@@ -490,11 +523,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
LOG_WARNING(
|
||||
Render_Vulkan,
|
||||
"RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
|
||||
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||
extensions.extended_dynamic_state2 = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state2 && is_qualcomm) {
|
||||
@@ -504,11 +535,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
|
||||
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||
extensions.extended_dynamic_state2 = false;
|
||||
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
||||
features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.extended_dynamic_state3 && is_radv) {
|
||||
@@ -540,9 +569,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (is_rdna2) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
|
||||
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
|
||||
extensions.vertex_input_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
|
||||
@@ -553,9 +582,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
LOG_WARNING(
|
||||
Render_Vulkan,
|
||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state");
|
||||
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
|
||||
extensions.vertex_input_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,8 +604,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
if (!features.shader_float16_int8.shaderFloat16) {
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax");
|
||||
extensions.sampler_filter_minmax = false;
|
||||
loaded_extensions.erase(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME);
|
||||
RemoveExtension(extensions.sampler_filter_minmax,
|
||||
VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,8 +613,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
|
||||
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
|
||||
extensions.vertex_input_dynamic_state = false;
|
||||
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
|
||||
@@ -612,8 +642,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
// mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
|
||||
LOG_WARNING(Render_Vulkan,
|
||||
"ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
|
||||
extensions.push_descriptor = false;
|
||||
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||
}
|
||||
}
|
||||
if (is_mvk) {
|
||||
@@ -1007,34 +1036,29 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||
return suitable;
|
||||
}
|
||||
|
||||
void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
|
||||
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
||||
LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
|
||||
loaded_extensions.erase(extension_name);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::RemoveUnsuitableExtensions() {
|
||||
// VK_EXT_custom_border_color
|
||||
extensions.custom_border_color = features.custom_border_color.customBorderColors &&
|
||||
features.custom_border_color.customBorderColorWithoutFormat;
|
||||
RemoveExtensionIfUnsuitable(extensions.custom_border_color,
|
||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
|
||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_depth_clip_control
|
||||
extensions.depth_clip_control = features.depth_clip_control.depthClipControl;
|
||||
RemoveExtensionIfUnsuitable(extensions.depth_clip_control,
|
||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
|
||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_extended_dynamic_state
|
||||
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
||||
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
|
||||
features.extended_dynamic_state,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_extended_dynamic_state2
|
||||
extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2;
|
||||
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state2,
|
||||
features.extended_dynamic_state2,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_extended_dynamic_state3
|
||||
dynamic_state3_blending =
|
||||
@@ -1048,35 +1072,38 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables;
|
||||
dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3;
|
||||
dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3;
|
||||
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state3,
|
||||
features.extended_dynamic_state3,
|
||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_provoking_vertex
|
||||
extensions.provoking_vertex =
|
||||
features.provoking_vertex.provokingVertexLast &&
|
||||
features.provoking_vertex.transformFeedbackPreservesProvokingVertex;
|
||||
RemoveExtensionIfUnsuitable(extensions.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex,
|
||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_shader_atomic_int64
|
||||
extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
|
||||
features.shader_atomic_int64.shaderSharedInt64Atomics;
|
||||
RemoveExtensionIfUnsuitable(extensions.shader_atomic_int64,
|
||||
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.shader_atomic_int64, features.shader_atomic_int64,
|
||||
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_shader_demote_to_helper_invocation
|
||||
extensions.shader_demote_to_helper_invocation =
|
||||
features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation;
|
||||
RemoveExtensionIfUnsuitable(extensions.shader_demote_to_helper_invocation,
|
||||
VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.shader_demote_to_helper_invocation,
|
||||
features.shader_demote_to_helper_invocation,
|
||||
VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_subgroup_size_control
|
||||
extensions.subgroup_size_control =
|
||||
features.subgroup_size_control.subgroupSizeControl &&
|
||||
properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize &&
|
||||
properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize;
|
||||
RemoveExtensionIfUnsuitable(extensions.subgroup_size_control,
|
||||
VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.subgroup_size_control,
|
||||
features.subgroup_size_control,
|
||||
VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_transform_feedback
|
||||
extensions.transform_feedback =
|
||||
@@ -1086,24 +1113,27 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
properties.transform_feedback.maxTransformFeedbackBuffers > 0 &&
|
||||
properties.transform_feedback.transformFeedbackQueries &&
|
||||
properties.transform_feedback.transformFeedbackDraw;
|
||||
RemoveExtensionIfUnsuitable(extensions.transform_feedback,
|
||||
VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.transform_feedback, features.transform_feedback,
|
||||
VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
|
||||
|
||||
// VK_EXT_vertex_input_dynamic_state
|
||||
extensions.vertex_input_dynamic_state =
|
||||
features.vertex_input_dynamic_state.vertexInputDynamicState;
|
||||
RemoveExtensionIfUnsuitable(extensions.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state,
|
||||
features.vertex_input_dynamic_state,
|
||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||
|
||||
// VK_KHR_pipeline_executable_properties
|
||||
if (Settings::values.renderer_shader_feedback.GetValue()) {
|
||||
extensions.pipeline_executable_properties =
|
||||
features.pipeline_executable_properties.pipelineExecutableInfo;
|
||||
RemoveExtensionIfUnsuitable(extensions.pipeline_executable_properties,
|
||||
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.pipeline_executable_properties,
|
||||
features.pipeline_executable_properties,
|
||||
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||
} else {
|
||||
extensions.pipeline_executable_properties = false;
|
||||
loaded_extensions.erase(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||
RemoveExtensionFeature(extensions.pipeline_executable_properties,
|
||||
features.pipeline_executable_properties,
|
||||
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
// VK_KHR_workgroup_memory_explicit_layout
|
||||
@@ -1113,8 +1143,9 @@ void Device::RemoveUnsuitableExtensions() {
|
||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess &&
|
||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess &&
|
||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout;
|
||||
RemoveExtensionIfUnsuitable(extensions.workgroup_memory_explicit_layout,
|
||||
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
||||
RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout,
|
||||
features.workgroup_memory_explicit_layout,
|
||||
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
void Device::SetupFamilies(VkSurfaceKHR surface) {
|
||||
|
||||
@@ -639,8 +639,17 @@ private:
|
||||
|
||||
// Remove extensions which have incomplete feature support.
|
||||
void RemoveUnsuitableExtensions();
|
||||
|
||||
void RemoveExtension(bool& extension, const std::string& extension_name);
|
||||
void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name);
|
||||
|
||||
template <typename Feature>
|
||||
void RemoveExtensionFeature(bool& extension, Feature& feature,
|
||||
const std::string& extension_name);
|
||||
template <typename Feature>
|
||||
void RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
|
||||
const std::string& extension_name);
|
||||
|
||||
/// Sets up queue families.
|
||||
void SetupFamilies(VkSurfaceKHR surface);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user