Added Vulkan PC OpenXR Support

This commit is contained in:
iChris4 committed 2026-09-21 00:31:46 +02:00
1 parent fbc9ce7217
commit e7b670b2cc
23 files changed
+2174 -22

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
"""Apply the versioned Aurora native Vulkan ABI to the pinned Dawn source tree."""
from pathlib import Path
import shutil, sys
root = Path(sys.argv[1]).resolve()
here = Path(__file__).resolve().parent
for name in ("aurora_vulkan_hooks.h", "aurora_vulkan_interop.inc"):
shutil.copyfile(here / name, root / "src/dawn/native/vulkan" / name)
shutil.copyfile(here.parent.parent / "include/aurora/dawn_vulkan_abi.h",
root / "src/dawn/native/vulkan/aurora_dawn_vulkan_abi.h")
p = root / "src/dawn/native/vulkan/VulkanBackend.cpp"
s = p.read_text()
if '#include "aurora_vulkan_interop.inc"' not in s:
s += '\n#include "aurora_vulkan_interop.inc"\n'
p.write_text(s)
p = root / "src/dawn/common/DynamicLib.cpp"
s = p.read_text()
# LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR requires an absolute filename. Vulkan's
# system loader is also tried by bare name; preserve the restricted default
# search directories for that case instead of failing with ERROR_INVALID_PARAMETER.
old = 'LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;'
new = '''((filename.size() > 2 && filename[1] == ':') || filename.starts_with("\\\\\\\\")
? LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR : 0) | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;'''
if old in s:
s = s.replace(old, new, 1)
p.write_text(s)
p = root / "src/dawn/native/vulkan/VulkanFunctions.cpp"
s = p.read_text()
if '#include "aurora_vulkan_hooks.h"' not in s:
marker = 'namespace dawn::native::vulkan {'
assert marker in s
s = s.replace(marker, '#include "aurora_vulkan_hooks.h"\n\n' + marker, 1)
for old, new in [
('GET_GLOBAL_PROC(CreateInstance);', 'CreateInstance = AuroraCreateInstance(GetInstanceProcAddr);'),
('GET_INSTANCE_PROC(CreateDevice);', 'CreateDevice = AuroraCreateDevice(GetInstanceProcAddr, instance);'),
('GET_INSTANCE_PROC(EnumeratePhysicalDevices);', 'EnumeratePhysicalDevices = AuroraEnumeratePhysicalDevices(GetInstanceProcAddr, instance);')]:
assert old in s, old
s = s.replace(old, old + '\n ' + new, 1)
p.write_text(s)
@@ -0,0 +1,9 @@
// Included only by the pinned Dawn source build.
#pragma once
#include "dawn/native/DawnNative.h"
#include "aurora_dawn_vulkan_abi.h"
namespace dawn::native::vulkan {
PFN_vkCreateInstance AuroraCreateInstance(PFN_vkGetInstanceProcAddr proc);
PFN_vkCreateDevice AuroraCreateDevice(PFN_vkGetInstanceProcAddr proc, VkInstance instance);
PFN_vkEnumeratePhysicalDevices AuroraEnumeratePhysicalDevices(PFN_vkGetInstanceProcAddr proc, VkInstance instance);
}
@@ -0,0 +1,118 @@
// Compiled inside VulkanBackend.cpp, using the pinned Dawn implementation.
#include "aurora_vulkan_hooks.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/vulkan/PhysicalDeviceVk.h"
#include "src/dawn/native/vulkan/QueueVk.h"
#include <mutex>
namespace dawn::native::vulkan {
namespace {
AuroraDawnVulkanHooks auroraHooks{};
std::recursive_mutex auroraHooksMutex;
PFN_vkGetInstanceProcAddr auroraGetProc = nullptr;
VkInstance auroraInstance = VK_NULL_HANDLE;
::VkResult VKAPI_CALL AuroraCreateInstanceImpl(const VkInstanceCreateInfo* info,
const VkAllocationCallbacks* allocator, VkInstance* instance) {
std::lock_guard lock(auroraHooksMutex);
if (auroraHooks.createInstance) return static_cast<::VkResult>(auroraHooks.createInstance(
auroraHooks.userdata, reinterpret_cast<void*>(auroraGetProc), info, allocator,
reinterpret_cast<void**>(instance)));
return reinterpret_cast<PFN_vkCreateInstance>(auroraGetProc(nullptr, "vkCreateInstance"))(info, allocator, instance);
}
::VkResult VKAPI_CALL AuroraCreateDeviceImpl(VkPhysicalDevice physical, const VkDeviceCreateInfo* info,
const VkAllocationCallbacks* allocator, VkDevice* device) {
std::lock_guard lock(auroraHooksMutex);
if (auroraHooks.createDevice) return static_cast<::VkResult>(auroraHooks.createDevice(
auroraHooks.userdata, reinterpret_cast<void*>(auroraGetProc), physical, info, allocator,
reinterpret_cast<void**>(device)));
return reinterpret_cast<PFN_vkCreateDevice>(auroraGetProc(auroraInstance, "vkCreateDevice"))(physical, info, allocator, device);
}
::VkResult VKAPI_CALL AuroraEnumerateImpl(VkInstance instance, uint32_t* count, VkPhysicalDevice* devices) {
std::lock_guard lock(auroraHooksMutex);
if (!auroraHooks.getPhysicalDevice) return reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
auroraGetProc(instance, "vkEnumeratePhysicalDevices"))(instance, count, devices);
void* physical = nullptr;
const auto result = static_cast<::VkResult>(auroraHooks.getPhysicalDevice(auroraHooks.userdata, instance, &physical));
if (result != VK_SUCCESS) return result;
if (!devices) { *count = 1; return VK_SUCCESS; }
if (*count == 0) return VK_INCOMPLETE;
devices[0] = static_cast<VkPhysicalDevice>(physical);
*count = 1;
return VK_SUCCESS;
}
struct AuroraDeviceGuard { decltype(std::declval<Device*>()->GetGuard()) guard; explicit AuroraDeviceGuard(Device* device) : guard(device->GetGuard()) {} };
}
PFN_vkCreateInstance AuroraCreateInstance(PFN_vkGetInstanceProcAddr proc) {
std::lock_guard lock(auroraHooksMutex);
if (!auroraHooks.createInstance) return reinterpret_cast<PFN_vkCreateInstance>(proc(nullptr, "vkCreateInstance"));
auroraGetProc = proc;
return AuroraCreateInstanceImpl;
}
PFN_vkCreateDevice AuroraCreateDevice(PFN_vkGetInstanceProcAddr proc, VkInstance instance) {
std::lock_guard lock(auroraHooksMutex);
if (!auroraHooks.createDevice) return reinterpret_cast<PFN_vkCreateDevice>(proc(instance, "vkCreateDevice"));
auroraGetProc = proc; auroraInstance = instance;
return AuroraCreateDeviceImpl;
}
PFN_vkEnumeratePhysicalDevices AuroraEnumeratePhysicalDevices(PFN_vkGetInstanceProcAddr proc, VkInstance instance) {
std::lock_guard lock(auroraHooksMutex);
if (!auroraHooks.getPhysicalDevice) return reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(proc(instance, "vkEnumeratePhysicalDevices"));
auroraGetProc = proc; auroraInstance = instance;
return AuroraEnumerateImpl;
}
extern "C" DAWN_NATIVE_EXPORT uint32_t AuroraDawnVulkanVersion() { return AURORA_DAWN_VULKAN_ABI; }
extern "C" DAWN_NATIVE_EXPORT int AuroraDawnVulkanConfigure(const AuroraDawnVulkanHooks* hooks) {
std::lock_guard lock(auroraHooksMutex);
// Called before adapter discovery, or cleared after Aurora shutdown. The
// runtime and hook storage must outlive all device creation calls.
auroraHooks = hooks ? *hooks : AuroraDawnVulkanHooks{};
return 1;
}
extern "C" DAWN_NATIVE_EXPORT int AuroraDawnVulkanGetHandles(void* handle, AuroraDawnVulkanHandles* out) {
auto* device = ToBackend(FromAPI(static_cast<WGPUDevice>(handle)));
auto guard = device->GetGuard();
if (!device->HasFeature(Feature::ImplicitDeviceSynchronization)) return 0;
*out = {device->GetVkInstance(), ToBackend(device->GetPhysicalDevice())->GetVkPhysicalDevice(),
device->GetVkDevice(), device->GetGraphicsQueueFamily(), 0};
return 1;
}
extern "C" DAWN_NATIVE_EXPORT void* AuroraDawnVulkanWrap(void* handle, const void* desc, uint64_t image) {
auto* device = ToBackend(FromAPI(static_cast<WGPUDevice>(handle)));
auto guard = device->GetGuard();
// Mirror DeviceBase::CreateTexture: fill the trivial frontend defaults
// (dimension, mip and sample counts) and validate before the backend reads
// them. An Undefined dimension would otherwise abort the first copy.
TextureDescriptor raw = reinterpret_cast<const TextureDescriptor*>(desc)->WithTrivialFrontendDefaults();
UnpackedPtr<TextureDescriptor> descriptor;
if (device->ConsumedError(ValidateAndUnpack(&raw), &descriptor)) return nullptr;
if (device->ConsumedError(ValidateTextureDescriptor(device, descriptor, AllowMultiPlanarTextureFormat::No))) return nullptr;
auto texture = SwapChainTexture::Create(device, descriptor, VkImage::CreateFromHandle(reinterpret_cast<::VkImage>(image)));
texture->SetIsSubresourceContentInitialized(true, texture->GetAllSubresources());
texture->UpdateUsage(wgpu::TextureUsage::RenderAttachment, wgpu::ShaderStage::None, texture->GetAllSubresources());
return ToAPI(ReturnToAPI(std::move(texture)));
}
extern "C" DAWN_NATIVE_EXPORT int AuroraDawnVulkanRelease(void* handle, void* const* textures, uint32_t count) {
auto* device = ToBackend(FromAPI(static_cast<WGPUDevice>(handle)));
auto guard = device->GetGuard();
auto* queue = ToBackend(device->GetQueue());
auto* context = queue->GetPendingRecordingContext();
for (uint32_t i = 0; i < count; ++i) {
auto* texture = ToBackend(FromAPI(static_cast<WGPUTexture>(textures[i])));
texture->TransitionUsageNow(context, wgpu::TextureUsage::RenderAttachment,
wgpu::ShaderStage::None, texture->GetAllSubresources());
}
return !device->ConsumedError(queue->SubmitPendingCommands());
}
extern "C" DAWN_NATIVE_EXPORT void* AuroraDawnVulkanLock(void* handle) {
auto* device = ToBackend(FromAPI(static_cast<WGPUDevice>(handle)));
return new AuroraDeviceGuard(device);
}
extern "C" DAWN_NATIVE_EXPORT void AuroraDawnVulkanUnlock(void* guard) {
delete static_cast<AuroraDeviceGuard*>(guard);
}
extern "C" DAWN_NATIVE_EXPORT int AuroraDawnVulkanDrain(void* handle) {
auto* device = ToBackend(FromAPI(static_cast<WGPUDevice>(handle)));
auto guard = device->GetGuard();
if (device->ConsumedError(ToBackend(device->GetQueue())->SubmitPendingCommands())) return 0;
return device->fn.QueueWaitIdle(ToBackend(device->GetQueue())->GetVkQueue()) == VK_SUCCESS;
}
}