win32: Import D3D12 resources into Vulkan renderer
This commit is contained in:
@@ -359,6 +359,12 @@ gdk_d3d12_texture_new_from_builder (GdkD3D12TextureBuilder *builder,
|
||||
#endif
|
||||
}
|
||||
|
||||
ID3D12Resource *
|
||||
gdk_d3d12_texture_get_resource (GdkD3D12Texture *self)
|
||||
{
|
||||
return self->resource;
|
||||
}
|
||||
|
||||
G_LOCK_DEFINE_STATIC(handle_creation);
|
||||
|
||||
HANDLE
|
||||
|
||||
@@ -11,6 +11,7 @@ GdkTexture * gdk_d3d12_texture_new_from_builder (GdkD3D1
|
||||
gpointer data,
|
||||
GError **error);
|
||||
|
||||
ID3D12Resource * gdk_d3d12_texture_get_resource (GdkD3D12Texture *self);
|
||||
HANDLE gdk_d3d12_texture_get_resource_handle (GdkD3D12Texture *self);
|
||||
|
||||
guint gdk_d3d12_texture_import_gl (GdkD3D12Texture *self,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,9 @@
|
||||
|
||||
#include <directx/d3d12.h>
|
||||
#include <epoxy/gl.h>
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
gboolean gdk_dxgi_format_is_supported (DXGI_FORMAT dxgi_format);
|
||||
GdkMemoryFormat gdk_dxgi_format_get_memory_format (DXGI_FORMAT dxgi_format,
|
||||
@@ -12,7 +15,10 @@ GdkMemoryFormat gdk_dxgi_format_get_memory_format (DXGI_FORMAT
|
||||
gboolean gdk_dxgi_format_is_yuv (DXGI_FORMAT dxgi_format);
|
||||
|
||||
GLenum gdk_dxgi_format_get_gl_format (DXGI_FORMAT dxgi_format);
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkFormat gdk_dxgi_format_get_vk_format (DXGI_FORMAT dxgi_format,
|
||||
VkComponentMapping *out_swizzle);
|
||||
#endif
|
||||
void gdk_dxgi_format_convert (DXGI_FORMAT src_format,
|
||||
gboolean src_premultiplied,
|
||||
const guchar *src_data,
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkgltextureprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include "gdk/win32/gdkd3d12textureprivate.h"
|
||||
#endif
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_semaphores
|
||||
#define GDK_ARRAY_TYPE_NAME GskSemaphores
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkSemaphore
|
||||
@@ -226,6 +230,23 @@ gsk_vulkan_frame_upload_texture (GskGpuFrame *frame,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_D3D12_TEXTURE (texture))
|
||||
{
|
||||
GdkD3D12Texture *d3d_texture = GDK_D3D12_TEXTURE (texture);
|
||||
GskGpuImage *image;
|
||||
|
||||
image = gsk_vulkan_image_new_for_d3d12resource (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
gdk_d3d12_texture_get_resource (d3d_texture),
|
||||
gdk_d3d12_texture_get_resource_handle (d3d_texture),
|
||||
gdk_memory_format_alpha (gdk_texture_get_format (texture)) != GDK_MEMORY_ALPHA_STRAIGHT);
|
||||
if (image)
|
||||
{
|
||||
gsk_gpu_image_toggle_ref_texture (image, texture);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GSK_GPU_FRAME_CLASS (gsk_vulkan_frame_parent_class)->upload_texture (frame, with_mipmap, texture);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <linux/dma-buf.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkdxgiformatprivate.h>
|
||||
#endif
|
||||
|
||||
struct _GskVulkanImage
|
||||
{
|
||||
@@ -1284,6 +1287,207 @@ gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
static gboolean
|
||||
gsk_vulkan_is_same_device (VkDevice vk_device,
|
||||
ID3D12DeviceChild *child)
|
||||
{
|
||||
/* FIXME: implement */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_vulkan_image_new_for_d3d12resource (GskVulkanDevice *device,
|
||||
ID3D12Resource *resource,
|
||||
HANDLE resource_handle,
|
||||
gboolean premultiplied)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
VkDevice vk_device;
|
||||
VkFormat vk_format;
|
||||
VkComponentMapping vk_components;
|
||||
VkSamplerYcbcrConversion vk_conversion;
|
||||
PFN_vkGetMemoryWin32HandlePropertiesKHR func_vkGetMemoryWin32HandlePropertiesKHR;
|
||||
VkResult res;
|
||||
GdkMemoryFormat format;
|
||||
GskGpuImageFlags flags;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
gsize memory_index;
|
||||
gboolean is_yuv;
|
||||
VkMemoryRequirements2 requirements = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
};
|
||||
VkMemoryWin32HandlePropertiesKHR handle_properties = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR,
|
||||
};
|
||||
|
||||
if (!gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_WIN32))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Vulkan does not support D3D12Resource import");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vk_device = gsk_vulkan_device_get_vk_device (device);
|
||||
func_vkGetMemoryWin32HandlePropertiesKHR = (PFN_vkGetMemoryWin32HandlePropertiesKHR) vkGetDeviceProcAddr (vk_device, "vkGetMemoryWin32HandlePropertiesKHR");
|
||||
ID3D12Resource_GetDesc (resource, &desc);
|
||||
|
||||
if (!gsk_vulkan_is_same_device (vk_device, (ID3D12DeviceChild *) resource))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Resource is from a different device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vk_format = gdk_dxgi_format_get_vk_format (desc.Format, &vk_components);
|
||||
if (vk_format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "GTK's Vulkan doesn't support DXGI format %u", desc.Format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_yuv = gdk_dxgi_format_is_yuv (desc.Format);
|
||||
if (is_yuv && !gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_YCBCR))
|
||||
{
|
||||
GDK_DEBUG (D3D12, "Vulkan driver cannot import DXGI format %u because it is YUV", desc.Format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!gsk_vulkan_device_supports_format (device,
|
||||
vk_format,
|
||||
dmabuf->modifier,
|
||||
dmabuf->n_planes,
|
||||
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
width, height,
|
||||
&flags))
|
||||
{
|
||||
GDK_DEBUG (DMABUF, "Vulkan driver does not support format %.4s::%016llx with %u planes",
|
||||
(char *) &dmabuf->fourcc, (unsigned long long) dmabuf->modifier, dmabuf->n_planes);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
flags = 0;
|
||||
#endif
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
|
||||
|
||||
self->device = g_object_ref (device);
|
||||
self->vk_tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
self->vk_format = vk_format;
|
||||
self->vk_pipeline_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
self->vk_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
self->vk_access = 0;
|
||||
|
||||
res = vkCreateImage (vk_device,
|
||||
&(VkImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = vk_format,
|
||||
.extent = { desc.Width, desc.Height, 1 },
|
||||
.mipLevels = desc.MipLevels,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = self->vk_tiling,
|
||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
(flags & GSK_GPU_IMAGE_NO_BLIT ? 0 : VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.initialLayout = self->vk_image_layout,
|
||||
.pNext = &(VkExternalMemoryImageCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&self->vk_image);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
GDK_DEBUG (D3D12, "vkCreateImage() failed: %s", gdk_vulkan_strerror (res));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags |
|
||||
(!premultiplied ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0) |
|
||||
(is_yuv ? (GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT) : 0) |
|
||||
(desc.MipLevels > 1 ? GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP : 0),
|
||||
gdk_dxgi_format_get_memory_format (desc.Format, premultiplied),
|
||||
desc.Width, desc.Height);
|
||||
|
||||
vkGetImageMemoryRequirements2 (vk_device,
|
||||
&(VkImageMemoryRequirementsInfo2) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.image = self->vk_image,
|
||||
},
|
||||
&requirements);
|
||||
// Vulkan memory import
|
||||
GSK_VK_CHECK (func_vkGetMemoryWin32HandlePropertiesKHR, vk_device,
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
resource_handle,
|
||||
&handle_properties);
|
||||
|
||||
memory_index = gsk_vulkan_device_find_allocator (device,
|
||||
handle_properties.memoryTypeBits,
|
||||
0,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
self->allocator = gsk_vulkan_device_get_external_allocator (device);
|
||||
gsk_vulkan_allocator_ref (self->allocator);
|
||||
|
||||
gsk_vulkan_alloc (self->allocator,
|
||||
requirements.memoryRequirements.size,
|
||||
requirements.memoryRequirements.alignment,
|
||||
&self->allocation);
|
||||
|
||||
GSK_VK_CHECK (vkAllocateMemory, vk_device,
|
||||
&(VkMemoryAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = requirements.memoryRequirements.size,
|
||||
.memoryTypeIndex = memory_index,
|
||||
.pNext = &(VkImportMemoryWin32HandleInfoKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
|
||||
.handle = resource_handle,
|
||||
.pNext = &(VkMemoryDedicatedAllocateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||
.image = self->vk_image,
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
&self->allocation.vk_memory);
|
||||
|
||||
GSK_VK_CHECK (vkBindImageMemory2, gsk_vulkan_device_get_vk_device (self->device),
|
||||
1,
|
||||
&(VkBindImageMemoryInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
||||
.image = self->vk_image,
|
||||
.memory = self->allocation.vk_memory,
|
||||
.memoryOffset = self->allocation.offset,
|
||||
});
|
||||
|
||||
if (is_yuv)
|
||||
{
|
||||
self->ycbcr = gsk_vulkan_device_get_ycbcr (device, vk_format);
|
||||
gsk_vulkan_ycbcr_ref (self->ycbcr);
|
||||
vk_conversion = gsk_vulkan_ycbcr_get_vk_conversion (self->ycbcr);
|
||||
}
|
||||
else
|
||||
vk_conversion = VK_NULL_HANDLE;
|
||||
|
||||
gsk_vulkan_image_create_view (self,
|
||||
vk_format,
|
||||
&vk_components,
|
||||
vk_conversion);
|
||||
|
||||
GDK_DEBUG (D3D12, "Vulkan uploaded %ux%u resource of %sformat %u",
|
||||
(guint) desc.Width, (guint) desc.Height,
|
||||
is_yuv ? "YUV " : "",
|
||||
desc.Format);
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gsk_vulkan_image_get_projection_matrix (GskGpuImage *image,
|
||||
graphene_matrix_t *out_projection)
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#include "gdk/gdkdmabufprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/win32/gdkwin32.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_IMAGE (gsk_vulkan_image_get_type ())
|
||||
@@ -47,6 +51,12 @@ GskGpuImage * gsk_vulkan_image_new_for_dmabuf (GskVulk
|
||||
GdkTexture * gsk_vulkan_image_to_dmabuf_texture (GskVulkanImage *self,
|
||||
GdkColorState *color_state);
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
GskGpuImage * gsk_vulkan_image_new_for_d3d12resource (GskVulkanDevice *device,
|
||||
ID3D12Resource *resource,
|
||||
HANDLE resource_handle,
|
||||
gboolean premultiplied);
|
||||
#endif
|
||||
|
||||
guchar * gsk_vulkan_image_get_data (GskVulkanImage *self,
|
||||
gsize *out_stride);
|
||||
|
||||
Reference in New Issue
Block a user