new input system
This commit is contained in:
parent
b3db40ebec
commit
ac2eb7fb0a
31 changed files with 3292 additions and 781 deletions
|
|
@ -176,158 +176,6 @@ VkBool32 onError(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMe
|
|||
|
||||
|
||||
#ifdef CRAFTER_GRAPHICS_WINDOW_WAYLAND
|
||||
constexpr CrafterKeys keysym_to_crafter_key(xkb_keysym_t sym)
|
||||
{
|
||||
switch (sym)
|
||||
{
|
||||
// Alphabet
|
||||
case XKB_KEY_a: return CrafterKeys::A;
|
||||
case XKB_KEY_b: return CrafterKeys::B;
|
||||
case XKB_KEY_c: return CrafterKeys::C;
|
||||
case XKB_KEY_d: return CrafterKeys::D;
|
||||
case XKB_KEY_e: return CrafterKeys::E;
|
||||
case XKB_KEY_f: return CrafterKeys::F;
|
||||
case XKB_KEY_g: return CrafterKeys::G;
|
||||
case XKB_KEY_h: return CrafterKeys::H;
|
||||
case XKB_KEY_i: return CrafterKeys::I;
|
||||
case XKB_KEY_j: return CrafterKeys::J;
|
||||
case XKB_KEY_k: return CrafterKeys::K;
|
||||
case XKB_KEY_l: return CrafterKeys::L;
|
||||
case XKB_KEY_m: return CrafterKeys::M;
|
||||
case XKB_KEY_n: return CrafterKeys::N;
|
||||
case XKB_KEY_o: return CrafterKeys::O;
|
||||
case XKB_KEY_p: return CrafterKeys::P;
|
||||
case XKB_KEY_q: return CrafterKeys::Q;
|
||||
case XKB_KEY_r: return CrafterKeys::R;
|
||||
case XKB_KEY_s: return CrafterKeys::S;
|
||||
case XKB_KEY_t: return CrafterKeys::T;
|
||||
case XKB_KEY_u: return CrafterKeys::U;
|
||||
case XKB_KEY_v: return CrafterKeys::V;
|
||||
case XKB_KEY_w: return CrafterKeys::W;
|
||||
case XKB_KEY_x: return CrafterKeys::X;
|
||||
case XKB_KEY_y: return CrafterKeys::Y;
|
||||
case XKB_KEY_z: return CrafterKeys::Z;
|
||||
|
||||
case XKB_KEY_A: return CrafterKeys::A;
|
||||
case XKB_KEY_B: return CrafterKeys::B;
|
||||
case XKB_KEY_C: return CrafterKeys::C;
|
||||
case XKB_KEY_D: return CrafterKeys::D;
|
||||
case XKB_KEY_E: return CrafterKeys::E;
|
||||
case XKB_KEY_F: return CrafterKeys::F;
|
||||
case XKB_KEY_G: return CrafterKeys::G;
|
||||
case XKB_KEY_H: return CrafterKeys::H;
|
||||
case XKB_KEY_I: return CrafterKeys::I;
|
||||
case XKB_KEY_J: return CrafterKeys::J;
|
||||
case XKB_KEY_K: return CrafterKeys::K;
|
||||
case XKB_KEY_L: return CrafterKeys::L;
|
||||
case XKB_KEY_M: return CrafterKeys::M;
|
||||
case XKB_KEY_N: return CrafterKeys::N;
|
||||
case XKB_KEY_O: return CrafterKeys::O;
|
||||
case XKB_KEY_P: return CrafterKeys::P;
|
||||
case XKB_KEY_Q: return CrafterKeys::Q;
|
||||
case XKB_KEY_R: return CrafterKeys::R;
|
||||
case XKB_KEY_S: return CrafterKeys::S;
|
||||
case XKB_KEY_T: return CrafterKeys::T;
|
||||
case XKB_KEY_U: return CrafterKeys::U;
|
||||
case XKB_KEY_V: return CrafterKeys::V;
|
||||
case XKB_KEY_W: return CrafterKeys::W;
|
||||
case XKB_KEY_X: return CrafterKeys::X;
|
||||
case XKB_KEY_Y: return CrafterKeys::Y;
|
||||
case XKB_KEY_Z: return CrafterKeys::Z;
|
||||
|
||||
// Numbers
|
||||
case XKB_KEY_0: return CrafterKeys::_0;
|
||||
case XKB_KEY_1: return CrafterKeys::_1;
|
||||
case XKB_KEY_2: return CrafterKeys::_2;
|
||||
case XKB_KEY_3: return CrafterKeys::_3;
|
||||
case XKB_KEY_4: return CrafterKeys::_4;
|
||||
case XKB_KEY_5: return CrafterKeys::_5;
|
||||
case XKB_KEY_6: return CrafterKeys::_6;
|
||||
case XKB_KEY_7: return CrafterKeys::_7;
|
||||
case XKB_KEY_8: return CrafterKeys::_8;
|
||||
case XKB_KEY_9: return CrafterKeys::_9;
|
||||
|
||||
// Function keys
|
||||
case XKB_KEY_F1: return CrafterKeys::F1;
|
||||
case XKB_KEY_F2: return CrafterKeys::F2;
|
||||
case XKB_KEY_F3: return CrafterKeys::F3;
|
||||
case XKB_KEY_F4: return CrafterKeys::F4;
|
||||
case XKB_KEY_F5: return CrafterKeys::F5;
|
||||
case XKB_KEY_F6: return CrafterKeys::F6;
|
||||
case XKB_KEY_F7: return CrafterKeys::F7;
|
||||
case XKB_KEY_F8: return CrafterKeys::F8;
|
||||
case XKB_KEY_F9: return CrafterKeys::F9;
|
||||
case XKB_KEY_F10: return CrafterKeys::F10;
|
||||
case XKB_KEY_F11: return CrafterKeys::F11;
|
||||
case XKB_KEY_F12: return CrafterKeys::F12;
|
||||
|
||||
// Control keys
|
||||
case XKB_KEY_Escape: return CrafterKeys::Escape;
|
||||
case XKB_KEY_Tab: return CrafterKeys::Tab;
|
||||
case XKB_KEY_Return: return CrafterKeys::Enter;
|
||||
case XKB_KEY_space: return CrafterKeys::Space;
|
||||
case XKB_KEY_BackSpace: return CrafterKeys::Backspace;
|
||||
case XKB_KEY_Delete: return CrafterKeys::Delete;
|
||||
case XKB_KEY_Insert: return CrafterKeys::Insert;
|
||||
case XKB_KEY_Home: return CrafterKeys::Home;
|
||||
case XKB_KEY_End: return CrafterKeys::End;
|
||||
case XKB_KEY_Page_Up: return CrafterKeys::PageUp;
|
||||
case XKB_KEY_Page_Down: return CrafterKeys::PageDown;
|
||||
case XKB_KEY_Caps_Lock: return CrafterKeys::CapsLock;
|
||||
case XKB_KEY_Num_Lock: return CrafterKeys::NumLock;
|
||||
case XKB_KEY_Scroll_Lock:return CrafterKeys::ScrollLock;
|
||||
|
||||
// Modifiers
|
||||
case XKB_KEY_Shift_L: return CrafterKeys::LeftShift;
|
||||
case XKB_KEY_Shift_R: return CrafterKeys::RightShift;
|
||||
case XKB_KEY_Control_L: return CrafterKeys::LeftCtrl;
|
||||
case XKB_KEY_Control_R: return CrafterKeys::RightCtrl;
|
||||
case XKB_KEY_Alt_L: return CrafterKeys::LeftAlt;
|
||||
case XKB_KEY_Alt_R: return CrafterKeys::RightAlt;
|
||||
case XKB_KEY_Super_L: return CrafterKeys::LeftSuper;
|
||||
case XKB_KEY_Super_R: return CrafterKeys::RightSuper;
|
||||
|
||||
// Arrows
|
||||
case XKB_KEY_Up: return CrafterKeys::Up;
|
||||
case XKB_KEY_Down: return CrafterKeys::Down;
|
||||
case XKB_KEY_Left: return CrafterKeys::Left;
|
||||
case XKB_KEY_Right: return CrafterKeys::Right;
|
||||
|
||||
// Keypad
|
||||
case XKB_KEY_KP_0: return CrafterKeys::keypad_0;
|
||||
case XKB_KEY_KP_1: return CrafterKeys::keypad_1;
|
||||
case XKB_KEY_KP_2: return CrafterKeys::keypad_2;
|
||||
case XKB_KEY_KP_3: return CrafterKeys::keypad_3;
|
||||
case XKB_KEY_KP_4: return CrafterKeys::keypad_4;
|
||||
case XKB_KEY_KP_5: return CrafterKeys::keypad_5;
|
||||
case XKB_KEY_KP_6: return CrafterKeys::keypad_6;
|
||||
case XKB_KEY_KP_7: return CrafterKeys::keypad_7;
|
||||
case XKB_KEY_KP_8: return CrafterKeys::keypad_8;
|
||||
case XKB_KEY_KP_9: return CrafterKeys::keypad_9;
|
||||
case XKB_KEY_KP_Enter: return CrafterKeys::keypad_enter;
|
||||
case XKB_KEY_KP_Add: return CrafterKeys::keypad_plus;
|
||||
case XKB_KEY_KP_Subtract: return CrafterKeys::keypad_minus;
|
||||
case XKB_KEY_KP_Multiply: return CrafterKeys::keypad_multiply;
|
||||
case XKB_KEY_KP_Divide: return CrafterKeys::keypad_divide;
|
||||
case XKB_KEY_KP_Decimal: return CrafterKeys::keypad_decimal;
|
||||
|
||||
// Punctuation
|
||||
case XKB_KEY_grave: return CrafterKeys::grave;
|
||||
case XKB_KEY_minus: return CrafterKeys::minus;
|
||||
case XKB_KEY_equal: return CrafterKeys::equal;
|
||||
case XKB_KEY_bracketleft: return CrafterKeys::bracket_left;
|
||||
case XKB_KEY_bracketright:return CrafterKeys::bracket_right;
|
||||
case XKB_KEY_backslash: return CrafterKeys::backslash;
|
||||
case XKB_KEY_semicolon: return CrafterKeys::semicolon;
|
||||
case XKB_KEY_apostrophe: return CrafterKeys::quote;
|
||||
case XKB_KEY_comma: return CrafterKeys::comma;
|
||||
case XKB_KEY_period: return CrafterKeys::period;
|
||||
case XKB_KEY_slash: return CrafterKeys::slash;
|
||||
|
||||
default: return CrafterKeys::CrafterKeysMax;
|
||||
}
|
||||
}
|
||||
|
||||
void Device::xdg_wm_base_handle_ping(void* data, xdg_wm_base* xdg_wm_base, std::uint32_t serial) {
|
||||
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||
}
|
||||
|
|
@ -336,8 +184,15 @@ void Device::handle_global(void *data, wl_registry *registry, std::uint32_t name
|
|||
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||
shm = reinterpret_cast<wl_shm*>(wl_registry_bind(registry, name, &wl_shm_interface, 1));
|
||||
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||
wl_seat* seat = reinterpret_cast<wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, 1));
|
||||
// Assign to Device::seat (not a fresh local) so SetClipboardText
|
||||
// and any other code that needs the seat post-init can find it.
|
||||
seat = reinterpret_cast<wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, 1));
|
||||
wl_seat_add_listener(seat, &seat_listener, nullptr);
|
||||
// If the manager came in first, the data device couldn't be
|
||||
// created yet — do it now that we have the seat.
|
||||
if (dataDeviceManager != nullptr && dataDevice == nullptr) {
|
||||
dataDevice = wl_data_device_manager_get_data_device(dataDeviceManager, seat);
|
||||
}
|
||||
} else if (compositor == nullptr && strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||
compositor = reinterpret_cast<wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 3));
|
||||
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||
|
|
@ -349,6 +204,16 @@ void Device::handle_global(void *data, wl_registry *registry, std::uint32_t name
|
|||
wpViewporter = reinterpret_cast<wp_viewporter*>(wl_registry_bind(registry, name, &wp_viewporter_interface, 1));
|
||||
} else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) {
|
||||
fractionalScaleManager = reinterpret_cast<wp_fractional_scale_manager_v1*>(wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1));
|
||||
} else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
|
||||
// v3 gives us the full set of data_source events (target / send /
|
||||
// cancelled / dnd_*). Universally supported by the compositors
|
||||
// we target — fall back path is the per-source listener simply
|
||||
// not getting the v3-only callbacks.
|
||||
dataDeviceManager = reinterpret_cast<wl_data_device_manager*>(
|
||||
wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3));
|
||||
if (seat != nullptr && dataDevice == nullptr) {
|
||||
dataDevice = wl_data_device_manager_get_data_device(dataDeviceManager, seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,23 +306,24 @@ void Device::keyboard_leave(void *data, wl_keyboard *keyboard, uint32_t serial,
|
|||
}
|
||||
|
||||
void Device::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
|
||||
xkb_keycode_t keycode = key + 8;
|
||||
xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, keycode);
|
||||
CrafterKeys crafterKey = keysym_to_crafter_key(keysym);
|
||||
// `key` is the kernel input-event-code (KEY_*). That is exactly what
|
||||
// :Keys returns for Wayland builds, so we store it verbatim with no
|
||||
// translation. The +8 X11 offset is only needed for the XKB layer,
|
||||
// which we still consult to produce UTF-8 text.
|
||||
KeyCode code = key;
|
||||
xkb_keycode_t xkbKeycode = key + 8;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if (focusedWindow->heldkeys[(std::uint8_t)crafterKey]) {
|
||||
focusedWindow->onKeyHold[(std::uint8_t)crafterKey].Invoke();
|
||||
focusedWindow->onAnyKeyHold.Invoke(crafterKey);
|
||||
if (focusedWindow->heldKeys.contains(code)) {
|
||||
focusedWindow->onRawKeyHold.Invoke(code);
|
||||
} else {
|
||||
focusedWindow->heldkeys[(std::uint8_t)crafterKey] = true;
|
||||
focusedWindow->onKeyDown[(std::uint8_t)crafterKey].Invoke();
|
||||
focusedWindow->onAnyKeyDown.Invoke(crafterKey);
|
||||
focusedWindow->heldKeys.insert(code);
|
||||
focusedWindow->onRawKeyDown.Invoke(code);
|
||||
}
|
||||
|
||||
std::string buf;
|
||||
buf.resize(16);
|
||||
int n = xkb_state_key_get_utf8(xkb_state, keycode, buf.data(), 16);
|
||||
int n = xkb_state_key_get_utf8(xkb_state, xkbKeycode, buf.data(), 16);
|
||||
std::string utf8;
|
||||
if (n > 0 && (unsigned char)buf[0] >= 0x20 && buf[0] != 0x7f) {
|
||||
buf.resize(n);
|
||||
|
|
@ -468,19 +334,18 @@ void Device::keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, ui
|
|||
// Replace the active repeat with this key — most recent press wins,
|
||||
// matching xkbcommon's typical behaviour and most desktop apps.
|
||||
keyRepeat.active = (keyRepeat.rate > 0);
|
||||
keyRepeat.key = crafterKey;
|
||||
keyRepeat.key = code;
|
||||
keyRepeat.utf8 = std::move(utf8);
|
||||
keyRepeat.pressTime = std::chrono::steady_clock::now();
|
||||
keyRepeat.lastFireTime = keyRepeat.pressTime;
|
||||
} else {
|
||||
focusedWindow->heldkeys[(std::uint8_t)crafterKey] = false;
|
||||
focusedWindow->onKeyUp[(std::uint8_t)crafterKey].Invoke();
|
||||
focusedWindow->onAnyKeyUp.Invoke(crafterKey);
|
||||
focusedWindow->heldKeys.erase(code);
|
||||
focusedWindow->onRawKeyUp.Invoke(code);
|
||||
|
||||
// If the released key was the one repeating, stop. Otherwise leave
|
||||
// the existing repeat alone (user pressed/released a modifier
|
||||
// mid-repeat etc.).
|
||||
if (keyRepeat.active && keyRepeat.key == crafterKey) {
|
||||
if (keyRepeat.active && keyRepeat.key == code) {
|
||||
keyRepeat.active = false;
|
||||
keyRepeat.utf8.clear();
|
||||
}
|
||||
|
|
@ -513,10 +378,8 @@ void Device::TickKeyRepeats() {
|
|||
// Catch up — emit one event per missed period so a paused frame doesn't
|
||||
// make the repeat permanently lag behind.
|
||||
while (now - keyRepeat.lastFireTime >= period) {
|
||||
focusedWindow->onKeyDown[(std::uint8_t)keyRepeat.key].Invoke();
|
||||
focusedWindow->onAnyKeyDown.Invoke(keyRepeat.key);
|
||||
focusedWindow->onKeyHold[(std::uint8_t)keyRepeat.key].Invoke();
|
||||
focusedWindow->onAnyKeyHold.Invoke(keyRepeat.key);
|
||||
focusedWindow->onRawKeyDown.Invoke(keyRepeat.key);
|
||||
focusedWindow->onRawKeyHold.Invoke(keyRepeat.key);
|
||||
if (!keyRepeat.utf8.empty()) {
|
||||
focusedWindow->onTextInput.Invoke(keyRepeat.utf8);
|
||||
}
|
||||
|
|
@ -673,11 +536,40 @@ void Device::Initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
// Enumerate available device extensions so we can opt into
|
||||
// VK_EXT_memory_decompression when the driver advertises it. Drivers
|
||||
// without it (AMD, Intel as of early 2026) get the CPU-decode fallback.
|
||||
{
|
||||
std::uint32_t extCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extCount, nullptr);
|
||||
std::vector<VkExtensionProperties> exts(extCount);
|
||||
vkEnumerateDeviceExtensionProperties(physDevice, nullptr, &extCount, exts.data());
|
||||
for (const VkExtensionProperties& e : exts) {
|
||||
if (std::strcmp(e.extensionName, VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME) == 0) {
|
||||
memoryDecompressionSupported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Properties query: chain memory-decompression props only when supported,
|
||||
// otherwise sType validation flags it as an unrecognized struct on
|
||||
// drivers that don't expose the extension.
|
||||
if (memoryDecompressionSupported) {
|
||||
memoryDecompressionProperties.pNext = const_cast<void*>(rayTracingProperties.pNext);
|
||||
rayTracingProperties.pNext = &memoryDecompressionProperties;
|
||||
}
|
||||
VkPhysicalDeviceProperties2 properties2 {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
||||
.pNext = &rayTracingProperties
|
||||
};
|
||||
vkGetPhysicalDeviceProperties2(physDevice, &properties2);
|
||||
|
||||
// Sanity-gate: GDeflate 1.0 must actually be in the supported method set.
|
||||
if (memoryDecompressionSupported &&
|
||||
(memoryDecompressionProperties.decompressionMethods & VK_MEMORY_DECOMPRESSION_METHOD_GDEFLATE_1_0_BIT_EXT) == 0) {
|
||||
memoryDecompressionSupported = false;
|
||||
}
|
||||
|
||||
uint32_t queueFamilyCount;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physDevice, &queueFamilyCount, NULL);
|
||||
|
|
@ -724,9 +616,26 @@ void Device::Initialize() {
|
|||
.shaderUntypedPointers = VK_TRUE,
|
||||
};
|
||||
|
||||
// Enables synchronization2 sentinels (VkMemoryBarrier2, VK_PIPELINE_STAGE_2_*,
|
||||
// VK_ACCESS_2_*) — required for VK_EXT_memory_decompression's sync tokens.
|
||||
VkPhysicalDeviceVulkan13Features features13 {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||||
.pNext = &untypedPointersFeatures,
|
||||
.synchronization2 = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceMemoryDecompressionFeaturesEXT memoryDecompressionFeatures {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_FEATURES_EXT,
|
||||
.pNext = &features13,
|
||||
.memoryDecompression = VK_TRUE,
|
||||
};
|
||||
void* postDecompressChain = memoryDecompressionSupported
|
||||
? static_cast<void*>(&memoryDecompressionFeatures)
|
||||
: static_cast<void*>(&features13);
|
||||
|
||||
VkPhysicalDeviceDescriptorHeapFeaturesEXT desciptorHeapFeatures {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_HEAP_FEATURES_EXT,
|
||||
.pNext = &untypedPointersFeatures,
|
||||
.pNext = postDecompressChain,
|
||||
.descriptorHeap = VK_TRUE,
|
||||
};
|
||||
|
||||
|
|
@ -787,12 +696,22 @@ void Device::Initialize() {
|
|||
}
|
||||
};
|
||||
|
||||
// Build the enabled-extension list dynamically so we can append the
|
||||
// optional VK_EXT_memory_decompression entry only when the driver
|
||||
// advertises it.
|
||||
std::vector<const char*> enabledDeviceExtensions(
|
||||
std::begin(deviceExtensionNames),
|
||||
std::end(deviceExtensionNames));
|
||||
if (memoryDecompressionSupported) {
|
||||
enabledDeviceExtensions.push_back(VK_EXT_MEMORY_DECOMPRESSION_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||
deviceCreateInfo.enabledExtensionCount = sizeof(deviceExtensionNames) / sizeof(const char*);
|
||||
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;
|
||||
deviceCreateInfo.enabledExtensionCount = static_cast<std::uint32_t>(enabledDeviceExtensions.size());
|
||||
deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data();
|
||||
deviceCreateInfo.pNext = &physical_features2;
|
||||
|
||||
uint32_t deviceLayerCount;
|
||||
|
|
@ -846,6 +765,19 @@ void Device::Initialize() {
|
|||
vkCmdPushDataEXT = reinterpret_cast<PFN_vkCmdPushDataEXT>(vkGetInstanceProcAddr(instance, "vkCmdPushDataEXT"));
|
||||
vkGetPhysicalDeviceDescriptorSizeEXT = reinterpret_cast<PFN_vkGetPhysicalDeviceDescriptorSizeEXT>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDescriptorSizeEXT"));
|
||||
vkGetDeviceFaultInfoEXT = reinterpret_cast<PFN_vkGetDeviceFaultInfoEXT>(vkGetInstanceProcAddr(instance, "vkGetDeviceFaultInfoEXT"));
|
||||
|
||||
if (memoryDecompressionSupported) {
|
||||
// vkGetDeviceProcAddr skips the loader trampoline that vkGetInstanceProcAddr
|
||||
// requires for device-level functions. The other PFNs above predate this
|
||||
// realization; opportunistic adoption for new entry points only.
|
||||
vkCmdDecompressMemoryEXT = reinterpret_cast<PFN_vkCmdDecompressMemoryEXT>(
|
||||
vkGetDeviceProcAddr(device, "vkCmdDecompressMemoryEXT"));
|
||||
if (vkCmdDecompressMemoryEXT == nullptr) {
|
||||
// Driver advertised the extension but didn't expose the entry
|
||||
// point — defensively fall back to CPU decode.
|
||||
memoryDecompressionSupported = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t Device::GetMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue