From a3711d4747e3eeadcf7cb0706b8ce543d9c69ca8 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 15 Apr 2024 11:00:19 +0100 Subject: [PATCH] vrclient_x64: Support submitting D3D12 textures. CW-Bug-Id: #23542 --- vrclient_x64/vkd3d-proton-interop.h | 90 +++++++ vrclient_x64/vrclient_main.c | 54 ++++ vrclient_x64/vrclient_private.h | 42 ++++ vrclient_x64/vrcompositor_manual.c | 369 +++++++++++++++++++++++----- 4 files changed, 492 insertions(+), 63 deletions(-) create mode 100644 vrclient_x64/vkd3d-proton-interop.h diff --git a/vrclient_x64/vkd3d-proton-interop.h b/vrclient_x64/vkd3d-proton-interop.h new file mode 100644 index 00000000..d88fb9b2 --- /dev/null +++ b/vrclient_x64/vkd3d-proton-interop.h @@ -0,0 +1,90 @@ +/*** Partially copied from autogenerated header by WIDL 6.4 from ../src-vkd3d-proton/include/vkd3d_device_vkd3d_ext.idl ***/ + +#pragma once + +#include +#include + +#ifndef __ID3D12DXVKInteropDevice_FWD_DEFINED__ +#define __ID3D12DXVKInteropDevice_FWD_DEFINED__ +typedef interface ID3D12DXVKInteropDevice ID3D12DXVKInteropDevice; +#endif + +#ifndef __ID3D12DXVKInteropDevice_INTERFACE_DEFINED__ +#define __ID3D12DXVKInteropDevice_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_ID3D12DXVKInteropDevice, 0x39da4e09, 0xbd1c, 0x4198, 0x9f,0xae, 0x86,0xbb,0xe3,0xbe,0x41,0xfd); +typedef struct ID3D12DXVKInteropDeviceVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + ID3D12DXVKInteropDevice *This, + REFIID riid, + void **object); + + ULONG (STDMETHODCALLTYPE *AddRef)( + ID3D12DXVKInteropDevice *This); + + ULONG (STDMETHODCALLTYPE *Release)( + ID3D12DXVKInteropDevice *This); + + /*** ID3D12DXVKInteropDevice methods ***/ + HRESULT (STDMETHODCALLTYPE *GetDXGIAdapter)( + ID3D12DXVKInteropDevice *This, + REFIID iid, + void **object); + + HRESULT (STDMETHODCALLTYPE *GetInstanceExtensions)( + ID3D12DXVKInteropDevice *This, + UINT *extension_count, + const char **extensions); + + HRESULT (STDMETHODCALLTYPE *GetDeviceExtensions)( + ID3D12DXVKInteropDevice *This, + UINT *extension_count, + const char **extensions); + + HRESULT (STDMETHODCALLTYPE *GetDeviceFeatures)( + ID3D12DXVKInteropDevice *This, + const VkPhysicalDeviceFeatures2 **features); + + HRESULT (STDMETHODCALLTYPE *GetVulkanHandles)( + ID3D12DXVKInteropDevice *This, + VkInstance *vk_instance, + VkPhysicalDevice *vk_physical_device, + VkDevice *vk_device); + + HRESULT (STDMETHODCALLTYPE *GetVulkanQueueInfo)( + ID3D12DXVKInteropDevice *This, + ID3D12CommandQueue *queue, + VkQueue *vk_queue, + UINT32 *vk_queue_family); + + void (STDMETHODCALLTYPE *GetVulkanImageLayout)( + ID3D12DXVKInteropDevice *This, + ID3D12Resource *resource, + D3D12_RESOURCE_STATES state, + VkImageLayout *vk_layout); + + HRESULT (STDMETHODCALLTYPE *GetVulkanResourceInfo)( + ID3D12DXVKInteropDevice *This, + ID3D12Resource *resource, + UINT64 *vk_handle, + UINT64 *buffer_offset); + + HRESULT (STDMETHODCALLTYPE *LockCommandQueue)( + ID3D12DXVKInteropDevice *This, + ID3D12CommandQueue *queue); + + HRESULT (STDMETHODCALLTYPE *UnlockCommandQueue)( + ID3D12DXVKInteropDevice *This, + ID3D12CommandQueue *queue); + + END_INTERFACE +} ID3D12DXVKInteropDeviceVtbl; + +interface ID3D12DXVKInteropDevice { + CONST_VTBL ID3D12DXVKInteropDeviceVtbl* lpVtbl; +}; +#endif diff --git a/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_main.c index 2d4b8066..c0bcb908 100644 --- a/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_main.c @@ -13,6 +13,7 @@ #include "initguid.h" #define COBJMACROS #include "d3d11_4.h" +#include "vkd3d-proton-interop.h" #include "dxvk-interop.h" #include "vrclient_private.h" @@ -311,6 +312,7 @@ static void *ivrclientcore_get_generic_interface( void *object, const char *name static void destroy_compositor_data(void) { TRACE("Destroying compositor data.\n"); + free_compositor_data_d3d12_device(); memset(&compositor_data, 0, sizeof(compositor_data)); } @@ -367,6 +369,58 @@ w_Texture_t vrclient_translate_texture_dxvk( const w_Texture_t *texture, w_VRVul return vktexture; } +w_Texture_t vrclient_translate_texture_d3d12( const w_Texture_t *texture, w_VRVulkanTextureData_t *vkdata, + ID3D12DXVKInteropDevice *d3d12_device, ID3D12Resource *d3d12_resource, + ID3D12CommandQueue *d3d12_queue, VkImageLayout *image_layout, + VkImageCreateInfo *image_info ) +{ + w_Texture_t vktexture; + VkImage image_handle; + UINT64 buffer_offset; + D3D12_RESOURCE_DESC resource_desc; + VkFormat vk_format = VK_FORMAT_UNDEFINED; + TRACE("%p %p %p %p %p %p\n", texture, vkdata, d3d12_device, d3d12_resource, d3d12_queue, image_layout); + d3d12_resource->lpVtbl->GetDesc(d3d12_resource, &resource_desc); + switch (resource_desc.Format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: vk_format = VK_FORMAT_R8G8B8A8_SRGB; break; + case DXGI_FORMAT_R8G8B8A8_UNORM: vk_format = VK_FORMAT_R8G8B8A8_UNORM; break; + default: + ERR("Unsupported DXGI format %#x.\n", resource_desc.Format); + return *texture; + } + if (resource_desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) + { + ERR("Unsupported resource dimension %#x.\n", resource_desc.Dimension); + return *texture; + } + + TRACE("DXGI format: %#x, width: %I64u, height: %u, mip levels: %u, array size: %u, sample count: %u, VkFormat %#x.\n", + resource_desc.Format, resource_desc.Width, resource_desc.Height, resource_desc.MipLevels, + resource_desc.DepthOrArraySize, resource_desc.SampleDesc.Count, vk_format); + + d3d12_device->lpVtbl->GetVulkanHandles(d3d12_device, &vkdata->m_pInstance, &vkdata->m_pPhysicalDevice, &vkdata->m_pDevice); + d3d12_device->lpVtbl->GetVulkanQueueInfo(d3d12_device, d3d12_queue, &vkdata->m_pQueue, &vkdata->m_nQueueFamilyIndex); + d3d12_device->lpVtbl->GetVulkanImageLayout(d3d12_device, d3d12_resource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, image_layout); + d3d12_device->lpVtbl->GetVulkanResourceInfo(d3d12_device, d3d12_resource, (UINT64*)&image_handle, &buffer_offset); + + /* For now, only these fields are used. */ + image_info->mipLevels = resource_desc.MipLevels; + image_info->arrayLayers = resource_desc.DepthOrArraySize; + + vkdata->m_nImage = (uint64_t)image_handle; + vkdata->m_nWidth = resource_desc.Width; + vkdata->m_nHeight = resource_desc.Height; + vkdata->m_nFormat = vk_format; + vkdata->m_nSampleCount = resource_desc.SampleDesc.Count; + + vktexture = *texture; + vktexture.handle = vkdata; + vktexture.eType = TextureType_Vulkan; + + return vktexture; +} + uint32_t __thiscall winIVRClientCore_IVRClientCore_002_Init( struct w_steam_iface *_this, uint32_t eApplicationType ) { struct IVRClientCore_IVRClientCore_002_Init_params params = diff --git a/vrclient_x64/vrclient_private.h b/vrclient_x64/vrclient_private.h index 2be9b50b..fb73c518 100644 --- a/vrclient_x64/vrclient_private.h +++ b/vrclient_x64/vrclient_private.h @@ -1,6 +1,7 @@ #include #include #include +#include #ifndef __cplusplus #include "unixlib.h" @@ -15,6 +16,8 @@ void *create_LinuxMatchmakingServerListResponse(void *win); #ifndef __cplusplus typedef struct ID3D11Device ID3D11Device; typedef struct IDXGIVkInteropDevice IDXGIVkInteropDevice; +typedef struct ID3D12DXVKInteropDevice ID3D12DXVKInteropDevice; +typedef struct ID3D12CommandQueue ID3D12CommandQueue; struct client_core_data { @@ -24,13 +27,44 @@ struct client_core_data SIZE_T created_interfaces_size; }; +#define VK_PROCS \ + X(vkAllocateCommandBuffers) \ + X(vkBeginCommandBuffer) \ + X(vkEndCommandBuffer) \ + X(vkQueueSubmit) \ + X(vkQueueWaitIdle) \ + X(vkFreeCommandBuffers) \ + X(vkCmdPipelineBarrier) \ + X(vkCreateCommandPool) \ + X(vkDestroyCommandPool) \ + X(vkDestroyFence) \ + X(vkCreateFence) \ + X(vkWaitForFences) \ + X(vkResetFences) + struct compositor_data { ID3D11Device *d3d11_device; + /* Vulkan queues aren't thread safe whereas D3D ones are. And + * the OpenVR runtime could use the Vulkan queue in some functions. + * So we need to lock the vulkan queues to prevent unsafe access using + * IDXGIVkInteropDevice or ID3D12DXVKInteropDevice interfaces. */ IDXGIVkInteropDevice *dxvk_device; + ID3D12DXVKInteropDevice *d3d12_device; + ID3D12CommandQueue *d3d12_queue; BOOL d3d11_explicit_handoff, handoff_called; void *client_core_linux_side; +#define X(proc) PFN_##proc p_##proc; + VK_PROCS +#undef X + VkDevice vk_device; + VkQueue vk_queue; + VkCommandPool vk_command_pool; + VkCommandBuffer vk_command_buffers[4]; + VkFence vk_fences[4]; + int command_buffer_index; + #ifndef __x86_64__ /* Digital action state change fixup hack. */ struct @@ -65,6 +99,7 @@ extern iface_destructor find_iface_destructor( const char *iface_version ); extern void init_rtti( char *base ); struct w_steam_iface *create_win_interface(const char *name, void *linux_side); +void free_compositor_data_d3d12_device(void); struct generic_interface { @@ -78,6 +113,13 @@ extern w_Texture_t vrclient_translate_texture_dxvk( const w_Texture_t *texture, VkImageLayout *image_layout, VkImageCreateInfo *image_info ); #endif /* __dxvk_interop_h__ */ +#ifdef __ID3D12DXVKInteropDevice_INTERFACE_DEFINED__ +extern w_Texture_t vrclient_translate_texture_d3d12( const w_Texture_t *texture, w_VRVulkanTextureData_t *vkdata, + ID3D12DXVKInteropDevice *d3d12_device, ID3D12Resource *d3d12_resource, + ID3D12CommandQueue *d3d12_queue, VkImageLayout *image_layout, + VkImageCreateInfo *image_info ); +#endif /* __ID3D12DXVKInteropDevice_INTERFACE_DEFINED__ */ + #include "vrclient_generated.h" #endif /* __cplusplus */ diff --git a/vrclient_x64/vrcompositor_manual.c b/vrclient_x64/vrcompositor_manual.c index 45436635..e34d5c23 100644 --- a/vrclient_x64/vrcompositor_manual.c +++ b/vrclient_x64/vrcompositor_manual.c @@ -7,6 +7,7 @@ #define COBJMACROS #include "d3d11_4.h" #include "dxvk-interop.h" +#include "vkd3d-proton-interop.h" #include "vrclient_private.h" WINE_DEFAULT_DEBUG_CHANNEL(vrclient); @@ -23,6 +24,8 @@ struct submit_state VkImageSubresourceRange subresources; IDXGIVkInteropSurface *dxvk_surface; IDXGIVkInteropDevice *dxvk_device; + ID3D12DXVKInteropDevice *d3d12_device; + ID3D12CommandQueue *d3d12_queue; }; static const w_Texture_t *load_compositor_texture_dxvk( uint32_t eye, const w_Texture_t *texture, uint32_t *flags, @@ -111,6 +114,240 @@ static void free_compositor_texture_dxvk( struct submit_state *state ) state->dxvk_surface->lpVtbl->Release( state->dxvk_surface ); } +void free_compositor_data_d3d12_device(void) +{ + if (!compositor_data.vk_device) return; + + for (int i = 0; i < ARRAY_SIZE(compositor_data.vk_fences); i++) + { + if (compositor_data.vk_fences[i] == VK_NULL_HANDLE) + continue; + compositor_data.p_vkDestroyFence(compositor_data.vk_device, compositor_data.vk_fences[i], NULL); + } + compositor_data.p_vkFreeCommandBuffers(compositor_data.vk_device, compositor_data.vk_command_pool, 3, compositor_data.vk_command_buffers); + compositor_data.p_vkDestroyCommandPool(compositor_data.vk_device, compositor_data.vk_command_pool, NULL); + + IUnknown_Release(compositor_data.d3d12_device); + IUnknown_Release(compositor_data.d3d12_queue); + compositor_data.d3d12_device = NULL; + compositor_data.d3d12_queue = NULL; + compositor_data.vk_device = VK_NULL_HANDLE; + compositor_data.vk_queue = VK_NULL_HANDLE; + compositor_data.command_buffer_index = 0; + memset(compositor_data.vk_fences, 0, sizeof(compositor_data.vk_fences)); + memset(compositor_data.vk_command_buffers, 0, sizeof(compositor_data.vk_command_buffers)); +} + +static void compositor_data_set_d3d12_device(ID3D12DXVKInteropDevice *d3d12_device, ID3D12CommandQueue *d3d12_queue, const w_VRVulkanTextureData_t *vkdata) +{ + const WCHAR winevulkan_dll[] = L"winevulkan.dll"; + HMODULE winevulkan = NULL; + PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr = NULL; + VkCommandPoolCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + .pNext = NULL, + .queueFamilyIndex = vkdata->m_nQueueFamilyIndex, + }; + VkCommandBufferAllocateInfo allocate_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = ARRAY_SIZE(compositor_data.vk_command_buffers), + }; + + if (compositor_data.d3d12_device == d3d12_device) + { + if (compositor_data.d3d12_queue != d3d12_queue) + { + IUnknown_Release(compositor_data.d3d12_queue); + compositor_data.d3d12_queue = d3d12_queue; + IUnknown_AddRef(d3d12_queue); + compositor_data.vk_queue = vkdata->m_pQueue; + } + return; + } + + free_compositor_data_d3d12_device(); + compositor_data.d3d12_device = d3d12_device; + compositor_data.d3d12_queue = d3d12_queue; + IUnknown_AddRef(compositor_data.d3d12_device); + IUnknown_AddRef(compositor_data.d3d12_queue); + + compositor_data.vk_device = vkdata->m_pDevice; + compositor_data.vk_queue = vkdata->m_pQueue; + + winevulkan = LoadLibraryW(winevulkan_dll); + p_vkGetDeviceProcAddr = (void *)GetProcAddress(winevulkan, "vkGetDeviceProcAddr"); +#define X(proc) compositor_data.p_##proc = (void *)p_vkGetDeviceProcAddr(compositor_data.vk_device, #proc); + VK_PROCS +#undef X + + compositor_data.p_vkCreateCommandPool(compositor_data.vk_device, &create_info, NULL, &compositor_data.vk_command_pool); + + allocate_info.commandPool = compositor_data.vk_command_pool; + compositor_data.p_vkAllocateCommandBuffers(compositor_data.vk_device, &allocate_info, compositor_data.vk_command_buffers); +} + +static void transition_image_layout(VkImage image, const VkImageSubresourceRange *subres, VkImageLayout from_layout, VkImageLayout to_layout) +{ + VkCommandBufferBeginInfo begin_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + VkImageMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .oldLayout = from_layout, + .newLayout = to_layout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange = *subres, + .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + }; + VkCommandBuffer command_buffer = compositor_data.vk_command_buffers[compositor_data.command_buffer_index]; + VkFence *fence = &compositor_data.vk_fences[compositor_data.command_buffer_index]; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &command_buffer, + }; + + if (from_layout == to_layout) return; + + if (*fence == VK_NULL_HANDLE) + { + VkFenceCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .pNext = NULL, + .flags = 0 + }; + if (compositor_data.p_vkCreateFence(compositor_data.vk_device, &create_info, NULL, fence) != VK_SUCCESS) + { + ERR("Cannot create fence\n"); + return; + } + } + else if (compositor_data.p_vkWaitForFences(compositor_data.vk_device, 1, fence, VK_FALSE, 1000000000) != VK_SUCCESS) + { + ERR("Failed to wait for fence\n"); + return; + } + + compositor_data.p_vkResetFences(compositor_data.vk_device, 1, fence); + compositor_data.p_vkBeginCommandBuffer(command_buffer, &begin_info); + compositor_data.p_vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + 0, 0, NULL, 0, NULL, 1, &barrier); + compositor_data.p_vkEndCommandBuffer(command_buffer); + compositor_data.p_vkQueueSubmit(compositor_data.vk_queue, 1, &submit_info, *fence); + compositor_data.command_buffer_index = (compositor_data.command_buffer_index + 1) % ARRAY_SIZE(compositor_data.vk_command_buffers); +} + +static const w_Texture_t *load_compositor_texture_d3d12( uint32_t eye, const w_Texture_t *texture, uint32_t *flags, + struct submit_state *state, uint32_t array_index ) +{ + static const uint32_t supported_flags = Submit_LensDistortionAlreadyApplied | Submit_FrameDiscontinuty | + Submit_TextureWithPose; + HRESULT hr; + w_VRVulkanTextureData_t vkdata; + VkImageCreateInfo image_info; + ID3D12Resource *resource_iface; + ID3D12CommandQueue *queue_iface; + w_D3D12TextureData_t *texture_data = texture->handle; + + TRACE( "texture = %p\n", texture ); + + if (!(resource_iface = texture_data->m_pResource) || !(queue_iface = texture_data->m_pCommandQueue)) + { + WARN( "Invalid D3D12 texture %p.\n", texture ); + return texture; + } + + hr = queue_iface->lpVtbl->GetDevice( queue_iface, &IID_ID3D12DXVKInteropDevice, (void **)&state->d3d12_device ); + if (FAILED(hr)) + { + WARN( "Failed to get vkd3d-proton device.\n" ); + return texture; + } + + state->texture.texture = vrclient_translate_texture_d3d12( texture, &vkdata, state->d3d12_device, resource_iface, queue_iface, &state->image_layout, + &image_info ); + + state->vkdata.m_nImage = vkdata.m_nImage; + state->vkdata.m_pDevice = vkdata.m_pDevice; + state->vkdata.m_pPhysicalDevice = vkdata.m_pPhysicalDevice; + state->vkdata.m_pInstance = vkdata.m_pInstance; + state->vkdata.m_pQueue = vkdata.m_pQueue; + state->vkdata.m_nQueueFamilyIndex = vkdata.m_nQueueFamilyIndex; + state->vkdata.m_nWidth = vkdata.m_nWidth; + state->vkdata.m_nHeight = vkdata.m_nHeight; + state->vkdata.m_nFormat = vkdata.m_nFormat; + state->vkdata.m_nSampleCount = vkdata.m_nSampleCount; + state->texture.texture.handle = &state->vkdata; + + if (*flags & Submit_TextureWithDepth) + { + WARN( "Ignoring depth.\n" ); + *flags &= ~Submit_TextureWithDepth; + } + + if (*flags & Submit_TextureWithPose) + ((w_VRTextureWithPose_t *)&state->texture.texture)->mDeviceToAbsoluteTracking = + ((w_VRTextureWithPose_t*)texture)->mDeviceToAbsoluteTracking; + + if (*flags & ~supported_flags) FIXME( "Unhandled flags %#x.\n", *flags ); + + state->d3d12_queue = queue_iface; + compositor_data_set_d3d12_device(state->d3d12_device, state->d3d12_queue, &vkdata); + IUnknown_Release(state->d3d12_device); + + if (image_info.arrayLayers > 1 || array_index != ~0u) + { + TRACE( "arrayLayers %u.\n", image_info.arrayLayers ); + state->vkdata.m_unArrayIndex = array_index != ~0u ? array_index : eye; + state->vkdata.m_unArraySize = image_info.arrayLayers; + *flags = *flags | Submit_VulkanTextureWithArrayData; + } + + state->subresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + state->subresources.baseMipLevel = 0; + state->subresources.levelCount = image_info.mipLevels; + state->subresources.baseArrayLayer = 0; + state->subresources.layerCount = image_info.arrayLayers; + + state->d3d12_device->lpVtbl->LockCommandQueue( state->d3d12_device, queue_iface ); + transition_image_layout((VkImage)state->vkdata.m_nImage, &state->subresources, state->image_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + return &state->texture.texture; +} + +static void free_compositor_texture_d3d12( struct submit_state *state ) +{ + if (!state->d3d12_device) return; + + transition_image_layout((VkImage)state->vkdata.m_nImage, &state->subresources, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, state->image_layout); + state->d3d12_device->lpVtbl->UnlockCommandQueue( state->d3d12_device, state->d3d12_queue ); +} + +static const w_Texture_t *load_compositor_texture( uint32_t eye, const w_Texture_t *texture, uint32_t *flags, + struct submit_state *state, uint32_t array_index ) +{ + switch (texture->eType) + { + case TextureType_DirectX: + return load_compositor_texture_dxvk( eye, texture, flags, state, array_index ); + case TextureType_DirectX12: + return load_compositor_texture_d3d12( eye, texture, flags, state, array_index ); + default: return texture; + } +} + +static void free_compositor_texture( uint32_t type, struct submit_state *state ) +{ + if (type == TextureType_DirectX) free_compositor_texture_dxvk( state ); + else if (type == TextureType_DirectX12) free_compositor_texture_d3d12( state ); +} + struct set_skybox_override_state { w_Texture_t textures[6]; @@ -206,27 +443,36 @@ static void set_skybox_override_done( const w_Texture_t *textures, uint32_t coun static void post_present_handoff_init( void *linux_side, unsigned int version ) { - if (!compositor_data.dxvk_device) return; - compositor_data.dxvk_device->lpVtbl->LockSubmissionQueue( compositor_data.dxvk_device ); + /* I sure hope no application will submit both D3D11 and D3D12 textures... */ + if (compositor_data.dxvk_device) + compositor_data.dxvk_device->lpVtbl->LockSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.d3d12_device) + compositor_data.d3d12_device->lpVtbl->LockCommandQueue( compositor_data.d3d12_device, compositor_data.d3d12_queue ); } static void post_present_handoff_done(void) { compositor_data.handoff_called = TRUE; - if (!compositor_data.dxvk_device) return; - compositor_data.dxvk_device->lpVtbl->ReleaseSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.dxvk_device) + compositor_data.dxvk_device->lpVtbl->ReleaseSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.d3d12_device) + compositor_data.d3d12_device->lpVtbl->UnlockCommandQueue( compositor_data.d3d12_device, compositor_data.d3d12_queue ); } static void wait_get_poses_init( void *linux_side ) { - if (!compositor_data.dxvk_device) return; - compositor_data.dxvk_device->lpVtbl->LockSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.dxvk_device) + compositor_data.dxvk_device->lpVtbl->LockSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.d3d12_device) + compositor_data.d3d12_device->lpVtbl->LockCommandQueue( compositor_data.d3d12_device, compositor_data.d3d12_queue ); } static void wait_get_poses_done( void *linux_side ) { - if (!compositor_data.dxvk_device) return; - compositor_data.dxvk_device->lpVtbl->ReleaseSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.dxvk_device) + compositor_data.dxvk_device->lpVtbl->ReleaseSubmissionQueue( compositor_data.dxvk_device ); + if (compositor_data.d3d12_device) + compositor_data.d3d12_device->lpVtbl->UnlockCommandQueue( compositor_data.d3d12_device, compositor_data.d3d12_queue ); } uint32_t __thiscall winIVRCompositor_IVRCompositor_009_Submit( struct w_steam_iface *_this, @@ -245,10 +491,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_009_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_009_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -293,10 +538,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_010_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_010_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -341,10 +585,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_011_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_011_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -389,10 +632,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_012_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_012_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -437,10 +679,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_013_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_013_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -485,10 +726,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_014_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_014_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -533,10 +773,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_015_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_015_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -600,10 +839,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_016_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_016_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -667,10 +905,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_017_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_017_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -734,10 +971,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_018_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_018_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -801,10 +1037,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_019_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_019_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -868,10 +1103,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_020_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_020_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -951,10 +1185,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_021_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_021_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1050,10 +1283,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_022_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_022_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1149,10 +1381,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_024_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_024_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1248,10 +1479,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_026_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_026_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1347,10 +1577,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_027_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_027_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1446,10 +1675,9 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_028_Submit( struct w_steam_if TRACE( "_this %p, eEye %u, pTexture %p (eType %u), pBounds %p, nSubmitFlags %#x\n", _this, eEye, pTexture, pTexture->eType, pBounds, nSubmitFlags ); compositor_data.handoff_called = FALSE; - if (pTexture->eType == TextureType_DirectX) - params.pTexture = load_compositor_texture_dxvk( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); + params.pTexture = load_compositor_texture( eEye, pTexture, ¶ms.nSubmitFlags, &state, ~0u ); VRCLIENT_CALL( IVRCompositor_IVRCompositor_028_Submit, ¶ms ); - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return params._ret; } @@ -1479,6 +1707,21 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_028_SubmitWithArrayIndex( str VRCLIENT_CALL( IVRCompositor_IVRCompositor_028_Submit, ¶ms ); ret = params._ret; } + else if (pTexture->eType == TextureType_DirectX12) + { + struct IVRCompositor_IVRCompositor_028_Submit_params params = + { + .linux_side = _this->u_iface, + .eEye = eEye, + .pTexture = pTexture, + .pBounds = pBounds, + .nSubmitFlags = nSubmitFlags, + }; + + params.pTexture = load_compositor_texture_d3d12( eEye, pTexture, ¶ms.nSubmitFlags, &state, unTextureArrayIndex ); + VRCLIENT_CALL( IVRCompositor_IVRCompositor_028_Submit, ¶ms ); + ret = params._ret; + } else { struct IVRCompositor_IVRCompositor_028_SubmitWithArrayIndex_params params = @@ -1494,7 +1737,7 @@ uint32_t __thiscall winIVRCompositor_IVRCompositor_028_SubmitWithArrayIndex( str VRCLIENT_CALL( IVRCompositor_IVRCompositor_028_SubmitWithArrayIndex, ¶ms ); ret = params._ret; } - if (pTexture->eType == TextureType_DirectX) free_compositor_texture_dxvk( &state ); + free_compositor_texture( pTexture->eType, &state ); return ret; }