mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-12 20:00:09 +00:00
Merge branch 'wip/otte/for-vulkan' into 'main'
vulkan: Add support for different image formats See merge request GNOME/gtk!6117
This commit is contained in:
commit
c40588886b
@ -36,6 +36,7 @@
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkrectangle.h"
|
||||
#include "gdkvulkancontext.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include <epoxy/egl.h>
|
||||
@ -1216,6 +1217,49 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_display_create_vulkan_context:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Creates a new `GdkVulkanContext` for use with @display.
|
||||
*
|
||||
* The context can not be used to draw to surfaces, it can only be
|
||||
* used for custom rendering or compute.
|
||||
*
|
||||
* If the creation of the `GdkVulkanContext` failed, @error will be set.
|
||||
*
|
||||
* Returns: (transfer full): the newly created `GdkVulkanContext`, or
|
||||
* %NULL on error
|
||||
*/
|
||||
GdkVulkanContext *
|
||||
gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (gdk_display_get_debug_flags (self) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
_("Vulkan support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GDK_DISPLAY_GET_CLASS (self)->vk_extension_name == NULL)
|
||||
{
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (self));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (self)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"display", self,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_init_gl (GdkDisplay *self)
|
||||
{
|
||||
|
@ -202,6 +202,9 @@ gulong _gdk_display_get_next_serial (GdkDisplay *display
|
||||
void _gdk_display_pause_events (GdkDisplay *display);
|
||||
void _gdk_display_unpause_events (GdkDisplay *display);
|
||||
|
||||
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
gboolean gdk_display_init_egl (GdkDisplay *display,
|
||||
|
@ -47,7 +47,11 @@ typedef struct _GdkVulkanContextPrivate GdkVulkanContextPrivate;
|
||||
struct _GdkVulkanContextPrivate {
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkSurfaceKHR surface;
|
||||
VkSurfaceFormatKHR image_format;
|
||||
struct {
|
||||
VkSurfaceFormatKHR vk_format;
|
||||
GdkMemoryFormat gdk_format;
|
||||
} formats[4];
|
||||
GdkMemoryDepth current_format;
|
||||
|
||||
VkSwapchainKHR swapchain;
|
||||
VkSemaphore draw_semaphore;
|
||||
@ -429,8 +433,8 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
.minImageCount = CLAMP (4,
|
||||
capabilities.minImageCount,
|
||||
capabilities.maxImageCount ? capabilities.maxImageCount : G_MAXUINT32),
|
||||
.imageFormat = priv->image_format.format,
|
||||
.imageColorSpace = priv->image_format.colorSpace,
|
||||
.imageFormat = priv->formats[priv->current_format].vk_format.format,
|
||||
.imageColorSpace = priv->formats[priv->current_format].vk_format.colorSpace,
|
||||
.imageExtent = capabilities.currentExtent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
@ -499,19 +503,20 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_supports_incremental_present (VkPhysicalDevice device)
|
||||
physical_device_supports_extension (VkPhysicalDevice device,
|
||||
const char *extension_name)
|
||||
{
|
||||
VkExtensionProperties *extensions;
|
||||
uint32_t n_device_extensions;
|
||||
|
||||
vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, NULL);
|
||||
GDK_VK_CHECK (vkEnumerateDeviceExtensionProperties, device, NULL, &n_device_extensions, NULL);
|
||||
|
||||
extensions = g_newa (VkExtensionProperties, n_device_extensions);
|
||||
vkEnumerateDeviceExtensionProperties (device, NULL, &n_device_extensions, extensions);
|
||||
GDK_VK_CHECK (vkEnumerateDeviceExtensionProperties, device, NULL, &n_device_extensions, extensions);
|
||||
|
||||
for (uint32_t i = 0; i < n_device_extensions; i++)
|
||||
{
|
||||
if (g_str_equal (extensions[i].extensionName, VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME))
|
||||
if (g_str_equal (extensions[i].extensionName, extension_name))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -527,6 +532,20 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
guint i;
|
||||
|
||||
if (depth != priv->current_format)
|
||||
{
|
||||
if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!gdk_vulkan_context_check_swapchain (context, &error))
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
priv->current_format = depth;
|
||||
}
|
||||
for (i = 0; i < priv->n_images; i++)
|
||||
{
|
||||
cairo_region_union (priv->regions[i], region);
|
||||
@ -665,6 +684,7 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (initable);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context));
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
|
||||
VkResult res;
|
||||
VkBool32 supported;
|
||||
uint32_t i;
|
||||
@ -673,6 +693,17 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
if (!priv->vulkan_ref)
|
||||
return FALSE;
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->formats); i++)
|
||||
{
|
||||
priv->formats[i].vk_format.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
priv->formats[i].vk_format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
priv->formats[i].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = GDK_VULKAN_CONTEXT_GET_CLASS (context)->create_surface (context, &priv->surface);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
@ -707,17 +738,73 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
&n_formats, formats);
|
||||
for (i = 0; i < n_formats; i++)
|
||||
{
|
||||
if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM)
|
||||
break;
|
||||
if (formats[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
continue;
|
||||
|
||||
switch ((int) formats[i].format)
|
||||
{
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
};
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
priv->formats[GDK_MEMORY_U16].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U16].gdk_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
priv->formats[GDK_MEMORY_FLOAT16].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_FLOAT16].gdk_format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
priv->formats[GDK_MEMORY_FLOAT32].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_FLOAT32].gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == n_formats)
|
||||
if (priv->formats[GDK_MEMORY_U8].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
"No supported image format found.");
|
||||
goto out_surface;
|
||||
}
|
||||
priv->image_format = formats[i];
|
||||
priv->has_present_region = device_supports_incremental_present (display->vk_physical_device);
|
||||
/* Ensure all the formats exist:
|
||||
* - If a format was found, keep that one.
|
||||
* - FLOAT32 chooses the best format we have.
|
||||
* - FLOAT16 and U16 pick the format FLOAT32 uses
|
||||
*/
|
||||
if (priv->formats[GDK_MEMORY_FLOAT32].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format != VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_FLOAT16];
|
||||
else if (priv->formats[GDK_MEMORY_U16].vk_format.format != VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U16];
|
||||
else
|
||||
priv->formats[GDK_MEMORY_FLOAT32] = priv->formats[GDK_MEMORY_U8];
|
||||
}
|
||||
if (priv->formats[GDK_MEMORY_FLOAT16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_FLOAT16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
if (priv->formats[GDK_MEMORY_U16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_U16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
|
||||
priv->has_present_region = physical_device_supports_extension (display->vk_physical_device,
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
if (!gdk_vulkan_context_check_swapchain (context, error))
|
||||
goto out_surface;
|
||||
@ -843,7 +930,7 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_FORMAT_UNDEFINED);
|
||||
|
||||
return priv->image_format.format;
|
||||
return priv->formats[priv->current_format].vk_format.format;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1039,6 +1126,10 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
for (i = first; i < last; i++)
|
||||
{
|
||||
uint32_t n_queue_props;
|
||||
|
||||
if (!physical_device_supports_extension (devices[i], VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
continue;
|
||||
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, NULL);
|
||||
VkQueueFamilyProperties *queue_props = g_newa (VkQueueFamilyProperties, n_queue_props);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, queue_props);
|
||||
@ -1049,7 +1140,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
GPtrArray *device_extensions;
|
||||
gboolean has_incremental_present;
|
||||
|
||||
has_incremental_present = device_supports_incremental_present (devices[i]);
|
||||
has_incremental_present = physical_device_supports_extension (devices[i],
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
device_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
|
@ -72,18 +72,16 @@ gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
|
||||
}
|
||||
|
||||
GskVulkanBuffer *
|
||||
gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
|
||||
gsize size)
|
||||
gsk_vulkan_buffer_new_map (GdkVulkanContext *context,
|
||||
gsize size,
|
||||
GskVulkanMapMode mode)
|
||||
{
|
||||
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
return gsk_vulkan_buffer_new_internal (context,
|
||||
size,
|
||||
(mode & GSK_VULKAN_READ ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0) |
|
||||
(mode & GSK_VULKAN_WRITE ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0));
|
||||
}
|
||||
|
||||
GskVulkanBuffer *
|
||||
gsk_vulkan_buffer_new_download (GdkVulkanContext *context,
|
||||
gsize size)
|
||||
{
|
||||
return gsk_vulkan_buffer_new_internal (context, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||
}
|
||||
void
|
||||
gsk_vulkan_buffer_free (GskVulkanBuffer *self)
|
||||
{
|
||||
|
@ -6,14 +6,20 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanBuffer GskVulkanBuffer;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSK_VULKAN_READ = (1 << 0),
|
||||
GSK_VULKAN_WRITE = (1 << 1),
|
||||
GSK_VULKAN_READWRITE = GSK_VULKAN_READ | GSK_VULKAN_WRITE
|
||||
} GskVulkanMapMode;
|
||||
|
||||
GskVulkanBuffer * gsk_vulkan_buffer_new (GdkVulkanContext *context,
|
||||
gsize size);
|
||||
GskVulkanBuffer * gsk_vulkan_buffer_new_storage (GdkVulkanContext *context,
|
||||
gsize size);
|
||||
GskVulkanBuffer * gsk_vulkan_buffer_new_staging (GdkVulkanContext *context,
|
||||
gsize size);
|
||||
GskVulkanBuffer * gsk_vulkan_buffer_new_download (GdkVulkanContext *context,
|
||||
gsize size);
|
||||
GskVulkanBuffer * gsk_vulkan_buffer_new_map (GdkVulkanContext *context,
|
||||
gsize size,
|
||||
GskVulkanMapMode mode);
|
||||
void gsk_vulkan_buffer_free (GskVulkanBuffer *buffer);
|
||||
|
||||
VkBuffer gsk_vulkan_buffer_get_buffer (GskVulkanBuffer *self);
|
||||
|
@ -6,6 +6,10 @@
|
||||
#include "gskvulkanmemoryprivate.h"
|
||||
#include "gskvulkanpipelineprivate.h"
|
||||
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _GskVulkanUploader
|
||||
@ -30,6 +34,8 @@ struct _GskVulkanImage
|
||||
|
||||
GdkVulkanContext *vulkan;
|
||||
|
||||
GdkMemoryFormat format;
|
||||
VkFormat vk_format;
|
||||
gsize width;
|
||||
gsize height;
|
||||
VkImageUsageFlags vk_usage;
|
||||
@ -196,8 +202,353 @@ gsk_vulkan_uploader_reset (GskVulkanUploader *self)
|
||||
self->staging_buffer_free_list = NULL;
|
||||
}
|
||||
|
||||
typedef struct _GskMemoryFormatInfo GskMemoryFormatInfo;
|
||||
|
||||
struct _GskMemoryFormatInfo
|
||||
{
|
||||
VkFormat format;
|
||||
VkComponentMapping components;
|
||||
};
|
||||
|
||||
static const GskMemoryFormatInfo *
|
||||
gsk_memory_format_get_vk_format_infos (GdkMemoryFormat format)
|
||||
{
|
||||
#define SWIZZLE(a, b, c, d) { VK_COMPONENT_SWIZZLE_ ## a, VK_COMPONENT_SWIZZLE_ ## b, VK_COMPONENT_SWIZZLE_ ## c, VK_COMPONENT_SWIZZLE_ ## d }
|
||||
#define DEFAULT_SWIZZLE SWIZZLE (R, G, B, A)
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_B8G8R8A8_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(B, G, R, A) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8G8B8A8_UNORM, SWIZZLE(G, B, A, R) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8G8B8A8_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_B8G8R8A8,
|
||||
GDK_MEMORY_A8R8G8B8,
|
||||
GDK_MEMORY_R8G8B8A8,
|
||||
GDK_MEMORY_A8B8G8R8,
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8G8B8_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_B8G8R8_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_R8G8B8_UNORM, SWIZZLE(B, G, R, A) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16G16B16_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16G16B16A16_UNORM, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_R16G16B16A16,
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16G16B16_SFLOAT, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16G16B16A16_SFLOAT, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_R16G16B16A16_FLOAT,
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R32G32B32_SFLOAT, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R32G32B32A32_SFLOAT, DEFAULT_SWIZZLE },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT,
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8G8_UNORM, SWIZZLE (R, R, R, G) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_G8A8,
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_G8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, ONE) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16G16_UNORM, SWIZZLE (R, R, R, G) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
#if 0
|
||||
GDK_MEMORY_G16A16
|
||||
#endif
|
||||
|
||||
case GDK_MEMORY_G16:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, ONE) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_A8:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R8_UNORM, SWIZZLE (R, R, R, R) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_A16:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_R16_UNORM, SWIZZLE (R, R, R, R) },
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
case GDK_MEMORY_G8A8:
|
||||
case GDK_MEMORY_G16A16:
|
||||
{
|
||||
static const GskMemoryFormatInfo info[] = {
|
||||
{ VK_FORMAT_UNDEFINED }
|
||||
};
|
||||
return info;
|
||||
}
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
#undef DEFAULT_SWIZZLE
|
||||
#undef SWIZZLE
|
||||
}
|
||||
|
||||
static GdkMemoryFormat
|
||||
gsk_memory_format_get_fallback (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
return GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
return GDK_MEMORY_A8R8G8B8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R16G16B16A16:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_G8A8:
|
||||
return GDK_MEMORY_G8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_G8:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
case GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
case GDK_MEMORY_G16A16:
|
||||
return GDK_MEMORY_G16A16_PREMULTIPLIED;
|
||||
case GDK_MEMORY_G16:
|
||||
return GDK_MEMORY_R16G16B16;
|
||||
case GDK_MEMORY_A8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_A16:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gsk_render_node_get_preferred_vulkan_format (GskRenderNode *node)
|
||||
{
|
||||
switch (gsk_render_node_get_preferred_depth (node))
|
||||
{
|
||||
case GDK_MEMORY_U8:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GDK_MEMORY_U16:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
return GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
default:
|
||||
g_return_val_if_reached (GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_vulkan_context_supports_format (GdkVulkanContext *context,
|
||||
VkFormat format)
|
||||
{
|
||||
VkFormatProperties properties;
|
||||
|
||||
vkGetPhysicalDeviceFormatProperties (gdk_vulkan_context_get_physical_device (context),
|
||||
format,
|
||||
&properties);
|
||||
|
||||
if ((properties.linearTilingFeatures & (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)) &&
|
||||
(properties.optimalTilingFeatures & (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_image_create_view (GskVulkanImage *self,
|
||||
const GskMemoryFormatInfo *format)
|
||||
{
|
||||
GSK_VK_CHECK (vkCreateImageView, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkImageViewCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = self->vk_image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = format->format,
|
||||
.components = format->components,
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&self->vk_image_view);
|
||||
}
|
||||
|
||||
static GskVulkanImage *
|
||||
gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
VkImageTiling tiling,
|
||||
@ -208,12 +559,30 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
{
|
||||
VkMemoryRequirements requirements;
|
||||
GskVulkanImage *self;
|
||||
const GskMemoryFormatInfo *vk_format;
|
||||
|
||||
g_assert (width > 0 && height > 0);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
for (vk_format = gsk_memory_format_get_vk_format_infos (format);
|
||||
vk_format->format != VK_FORMAT_UNDEFINED;
|
||||
vk_format++)
|
||||
{
|
||||
if (gsk_vulkan_context_supports_format (context, vk_format->format))
|
||||
break;
|
||||
}
|
||||
if (vk_format->format != VK_FORMAT_UNDEFINED)
|
||||
break;
|
||||
|
||||
format = gsk_memory_format_get_fallback (format);
|
||||
}
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_IMAGE, NULL);
|
||||
|
||||
self->vulkan = g_object_ref (context);
|
||||
self->format = format;
|
||||
self->vk_format = vk_format->format;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->vk_usage = usage;
|
||||
@ -225,7 +594,7 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.format = vk_format->format,
|
||||
.extent = { width, height, 1 },
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
@ -251,36 +620,10 @@ gsk_vulkan_image_new (GdkVulkanContext *context,
|
||||
self->vk_image,
|
||||
gsk_vulkan_memory_get_device_memory (self->memory),
|
||||
0);
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_image_ensure_view (GskVulkanImage *self,
|
||||
VkFormat format)
|
||||
{
|
||||
if (self->vk_image_view == VK_NULL_HANDLE)
|
||||
GSK_VK_CHECK (vkCreateImageView, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkImageViewCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = self->vk_image,
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = format,
|
||||
.components = {
|
||||
.r = VK_COMPONENT_SWIZZLE_R,
|
||||
.g = VK_COMPONENT_SWIZZLE_G,
|
||||
.b = VK_COMPONENT_SWIZZLE_B,
|
||||
.a = VK_COMPONENT_SWIZZLE_A,
|
||||
},
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
},
|
||||
NULL,
|
||||
&self->vk_image_view);
|
||||
gsk_vulkan_image_create_view (self, vk_format);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
@ -293,9 +636,11 @@ gsk_vulkan_image_new_from_texture (GskVulkanUploader *uploader,
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
result = gsk_vulkan_image_new_for_upload (uploader,
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
gsk_vulkan_image_map_memory (result, uploader, &map);
|
||||
gdk_texture_downloader_set_format (downloader, result->format);
|
||||
gsk_vulkan_image_map_memory (result, uploader, GSK_VULKAN_WRITE, &map);
|
||||
gdk_texture_downloader_download_into (downloader, map.data, map.stride);
|
||||
gsk_vulkan_image_unmap_memory (result, uploader, &map);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
@ -304,12 +649,14 @@ gsk_vulkan_image_new_from_texture (GskVulkanUploader *uploader,
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_for_upload (GskVulkanUploader *uploader,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
|
||||
self = gsk_vulkan_image_new (uploader->vulkan,
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
@ -319,19 +666,34 @@ gsk_vulkan_image_new_for_upload (GskVulkanUploader *uploader,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_image_map_memory_direct (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader,
|
||||
GskVulkanMapMode mode,
|
||||
GskVulkanImageMap *map)
|
||||
{
|
||||
VkImageSubresource image_res;
|
||||
VkSubresourceLayout image_layout;
|
||||
|
||||
if (self->vk_image_layout != VK_IMAGE_LAYOUT_PREINITIALIZED)
|
||||
{
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
FALSE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
(mode & GSK_VULKAN_READ ? VK_ACCESS_MEMORY_READ_BIT : 0) |
|
||||
(mode & GSK_VULKAN_WRITE ? VK_ACCESS_MEMORY_WRITE_BIT : 0));
|
||||
|
||||
if (mode & GSK_VULKAN_READ)
|
||||
{
|
||||
gsk_vulkan_uploader_upload (uploader);
|
||||
GSK_VK_CHECK (vkQueueWaitIdle, gdk_vulkan_context_get_queue (self->vulkan));
|
||||
}
|
||||
}
|
||||
|
||||
image_res.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
image_res.mipLevel = 0;
|
||||
image_res.arrayLayer = 0;
|
||||
@ -339,6 +701,7 @@ gsk_vulkan_image_map_memory_direct (GskVulkanImage *self,
|
||||
vkGetImageSubresourceLayout (gdk_vulkan_context_get_device (self->vulkan),
|
||||
self->vk_image, &image_res, &image_layout);
|
||||
|
||||
map->mode = mode;
|
||||
map->staging_buffer = NULL;
|
||||
map->data = gsk_vulkan_memory_map (self->memory) + image_layout.offset;
|
||||
map->stride = image_layout.rowPitch;
|
||||
@ -361,13 +724,52 @@ gsk_vulkan_image_unmap_memory_direct (GskVulkanImage *self,
|
||||
static void
|
||||
gsk_vulkan_image_map_memory_indirect (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader,
|
||||
GskVulkanMapMode mode,
|
||||
GskVulkanImageMap *map)
|
||||
{
|
||||
gsize buffer_size = self->width * self->height * 4;
|
||||
map->mode = mode;
|
||||
map->stride = self->width * gdk_memory_format_bytes_per_pixel (self->format);
|
||||
map->staging_buffer = gsk_vulkan_buffer_new_map (uploader->vulkan, self->height * map->stride, mode);
|
||||
|
||||
if (self->vk_image_layout != VK_IMAGE_LAYOUT_PREINITIALIZED)
|
||||
{
|
||||
if (mode & GSK_VULKAN_READ)
|
||||
{
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
FALSE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
vkCmdCopyImageToBuffer (gsk_vulkan_uploader_get_copy_buffer (uploader),
|
||||
self->vk_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
gsk_vulkan_buffer_get_buffer (map->staging_buffer),
|
||||
1,
|
||||
(VkBufferImageCopy[1]) {
|
||||
{
|
||||
.bufferOffset = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
},
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = {
|
||||
.width = self->width,
|
||||
.height = self->height,
|
||||
.depth = 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
gsk_vulkan_uploader_upload (uploader);
|
||||
GSK_VK_CHECK (vkQueueWaitIdle, gdk_vulkan_context_get_queue (self->vulkan));
|
||||
}
|
||||
}
|
||||
|
||||
map->staging_buffer = gsk_vulkan_buffer_new_staging (uploader->vulkan, buffer_size);
|
||||
map->data = gsk_vulkan_buffer_map (map->staging_buffer);
|
||||
map->stride = self->width * 4;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -377,70 +779,75 @@ gsk_vulkan_image_unmap_memory_indirect (GskVulkanImage *self,
|
||||
{
|
||||
gsk_vulkan_buffer_unmap (map->staging_buffer);
|
||||
|
||||
gsk_vulkan_uploader_add_buffer_barrier (uploader,
|
||||
FALSE,
|
||||
&(VkBufferMemoryBarrier) {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = gsk_vulkan_buffer_get_buffer (map->staging_buffer),
|
||||
.offset = 0,
|
||||
.size = VK_WHOLE_SIZE,
|
||||
});
|
||||
if (map->mode & GSK_VULKAN_WRITE)
|
||||
{
|
||||
gsk_vulkan_uploader_add_buffer_barrier (uploader,
|
||||
FALSE,
|
||||
&(VkBufferMemoryBarrier) {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
|
||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.buffer = gsk_vulkan_buffer_get_buffer (map->staging_buffer),
|
||||
.offset = 0,
|
||||
.size = VK_WHOLE_SIZE,
|
||||
});
|
||||
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
FALSE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
FALSE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
|
||||
vkCmdCopyBufferToImage (gsk_vulkan_uploader_get_copy_buffer (uploader),
|
||||
gsk_vulkan_buffer_get_buffer (map->staging_buffer),
|
||||
self->vk_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
(VkBufferImageCopy[1]) {
|
||||
{
|
||||
.bufferOffset = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
},
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = {
|
||||
.width = self->width,
|
||||
.height = self->height,
|
||||
.depth = 1
|
||||
vkCmdCopyBufferToImage (gsk_vulkan_uploader_get_copy_buffer (uploader),
|
||||
gsk_vulkan_buffer_get_buffer (map->staging_buffer),
|
||||
self->vk_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
(VkBufferImageCopy[1]) {
|
||||
{
|
||||
.bufferOffset = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
},
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = {
|
||||
.width = self->width,
|
||||
.height = self->height,
|
||||
.depth = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list,
|
||||
map->staging_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_vulkan_buffer_free (map->staging_buffer);
|
||||
}
|
||||
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
TRUE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_ACCESS_SHADER_READ_BIT);
|
||||
|
||||
uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list,
|
||||
map->staging_buffer);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_vulkan_image_map_memory (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader,
|
||||
GskVulkanMapMode mode,
|
||||
GskVulkanImageMap *map)
|
||||
{
|
||||
g_assert (self->vk_image_layout == VK_IMAGE_LAYOUT_UNDEFINED ||
|
||||
self->vk_image_layout == VK_IMAGE_LAYOUT_PREINITIALIZED);
|
||||
|
||||
if (!GSK_DEBUG_CHECK (STAGING) && gsk_vulkan_memory_can_map (self->memory, TRUE))
|
||||
gsk_vulkan_image_map_memory_direct (self, uploader, map);
|
||||
gsk_vulkan_image_map_memory_direct (self, uploader, mode, map);
|
||||
else
|
||||
gsk_vulkan_image_map_memory_indirect (self, uploader, map);
|
||||
gsk_vulkan_image_map_memory_indirect (self, uploader, mode, map);
|
||||
}
|
||||
|
||||
void
|
||||
@ -469,29 +876,17 @@ gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->vk_image = image;
|
||||
self->vk_format = format;
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
gsk_vulkan_image_create_view (self,
|
||||
&(GskMemoryFormatInfo) {
|
||||
format,
|
||||
{ VK_COMPONENT_SWIZZLE_R,
|
||||
VK_COMPONENT_SWIZZLE_G,
|
||||
VK_COMPONENT_SWIZZLE_B,
|
||||
VK_COMPONENT_SWIZZLE_A
|
||||
}
|
||||
});
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -504,6 +899,7 @@ gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
|
||||
GskVulkanImage *self;
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
@ -512,22 +908,22 @@ gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
|
||||
0,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
GskVulkanImage *
|
||||
gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
|
||||
GdkMemoryFormat preferred_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskVulkanImage *self;
|
||||
|
||||
self = gsk_vulkan_image_new (context,
|
||||
preferred_format,
|
||||
width,
|
||||
height,
|
||||
VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_TILING_LINEAR,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||
@ -535,8 +931,6 @@ gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -544,54 +938,18 @@ GdkTexture *
|
||||
gsk_vulkan_image_download (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader)
|
||||
{
|
||||
GskVulkanBuffer *buffer;
|
||||
GskVulkanImageMap map;
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
guchar *mem;
|
||||
|
||||
gsk_vulkan_uploader_add_image_barrier (uploader,
|
||||
FALSE,
|
||||
self,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
|
||||
buffer = gsk_vulkan_buffer_new_download (self->vulkan, self->width * self->height * 4);
|
||||
|
||||
vkCmdCopyImageToBuffer (gsk_vulkan_uploader_get_copy_buffer (uploader),
|
||||
self->vk_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
gsk_vulkan_buffer_get_buffer (buffer),
|
||||
1,
|
||||
(VkBufferImageCopy[1]) {
|
||||
{
|
||||
.bufferOffset = 0,
|
||||
.imageSubresource = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
},
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = {
|
||||
.width = self->width,
|
||||
.height = self->height,
|
||||
.depth = 1
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
gsk_vulkan_uploader_upload (uploader);
|
||||
|
||||
GSK_VK_CHECK (vkQueueWaitIdle, gdk_vulkan_context_get_queue (self->vulkan));
|
||||
|
||||
mem = gsk_vulkan_buffer_map (buffer);
|
||||
bytes = g_bytes_new (mem, self->width * self->height * 4);
|
||||
gsk_vulkan_image_map_memory (self, uploader, GSK_VULKAN_READ, &map);
|
||||
bytes = g_bytes_new (map.data, map.stride * self->height);
|
||||
texture = gdk_memory_texture_new (self->width, self->height,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
self->format,
|
||||
bytes,
|
||||
self->width * 4);
|
||||
gsk_vulkan_buffer_unmap (buffer);
|
||||
gsk_vulkan_buffer_free (buffer);
|
||||
map.stride);
|
||||
g_bytes_unref (bytes);
|
||||
gsk_vulkan_image_unmap_memory (self, uploader, &map);
|
||||
|
||||
return texture;
|
||||
}
|
||||
@ -613,7 +971,7 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self,
|
||||
for (int i = 0; i < num_regions; i++)
|
||||
size += regions[i].width * regions[i].height * 4;
|
||||
|
||||
staging = gsk_vulkan_buffer_new_staging (uploader->vulkan, size);
|
||||
staging = gsk_vulkan_buffer_new_map (uploader->vulkan, size, GSK_VULKAN_WRITE);
|
||||
mem = gsk_vulkan_buffer_map (staging);
|
||||
|
||||
bufferImageCopy = alloca (sizeof (VkBufferImageCopy) * num_regions);
|
||||
@ -672,8 +1030,6 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self,
|
||||
VK_ACCESS_SHADER_READ_BIT);
|
||||
|
||||
uploader->staging_buffer_free_list = g_slist_prepend (uploader->staging_buffer_free_list, staging);
|
||||
|
||||
gsk_vulkan_image_ensure_view (self, VK_FORMAT_B8G8R8A8_UNORM);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -738,3 +1094,9 @@ gsk_vulkan_image_get_image_view (GskVulkanImage *self)
|
||||
{
|
||||
return self->vk_image_view;
|
||||
}
|
||||
|
||||
VkFormat
|
||||
gsk_vulkan_image_get_vk_format (GskVulkanImage *self)
|
||||
{
|
||||
return self->vk_format;
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gskrendernode.h>
|
||||
|
||||
#include "gskvulkanbufferprivate.h"
|
||||
#include "gskvulkancommandpoolprivate.h"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GskVulkanUploader GskVulkanUploader;
|
||||
@ -19,6 +22,8 @@ void gsk_vulkan_uploader_free (GskVulk
|
||||
void gsk_vulkan_uploader_reset (GskVulkanUploader *self);
|
||||
void gsk_vulkan_uploader_upload (GskVulkanUploader *self);
|
||||
|
||||
GdkMemoryFormat gsk_render_node_get_preferred_vulkan_format (GskRenderNode *node);
|
||||
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_swapchain (GdkVulkanContext *context,
|
||||
VkImage image,
|
||||
VkFormat format,
|
||||
@ -40,13 +45,11 @@ void gsk_vulkan_image_upload_regions (GskVulk
|
||||
GskVulkanUploader *uploader,
|
||||
guint num_regions,
|
||||
GskImageRegion *regions);
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_framebuffer (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height);
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_atlas (GdkVulkanContext *context,
|
||||
gsize width,
|
||||
gsize height);
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_offscreen (GdkVulkanContext *context,
|
||||
GdkMemoryFormat preferred_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
@ -58,17 +61,20 @@ typedef struct _GskVulkanImageMap GskVulkanImageMap;
|
||||
struct _GskVulkanImageMap
|
||||
{
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
gsize stride;
|
||||
GskVulkanMapMode mode;
|
||||
|
||||
/* private */
|
||||
gpointer staging_buffer;
|
||||
GskVulkanBuffer *staging_buffer;
|
||||
};
|
||||
|
||||
GskVulkanImage * gsk_vulkan_image_new_for_upload (GskVulkanUploader *uploader,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
void gsk_vulkan_image_map_memory (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader,
|
||||
GskVulkanMapMode mode,
|
||||
GskVulkanImageMap *map);
|
||||
void gsk_vulkan_image_unmap_memory (GskVulkanImage *self,
|
||||
GskVulkanUploader *uploader,
|
||||
@ -78,6 +84,7 @@ gsize gsk_vulkan_image_get_width (GskVulk
|
||||
gsize gsk_vulkan_image_get_height (GskVulkanImage *self);
|
||||
VkImage gsk_vulkan_image_get_image (GskVulkanImage *self);
|
||||
VkImageView gsk_vulkan_image_get_image_view (GskVulkanImage *self);
|
||||
VkFormat gsk_vulkan_image_get_vk_format (GskVulkanImage *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -50,10 +50,8 @@ struct _GskVulkanRender
|
||||
graphene_rect_t viewport;
|
||||
cairo_region_t *clip;
|
||||
|
||||
GHashTable *framebuffers;
|
||||
GskVulkanCommandPool *command_pool;
|
||||
VkFence fence;
|
||||
VkRenderPass render_pass;
|
||||
VkDescriptorSetLayout descriptor_set_layout;
|
||||
VkPipelineLayout pipeline_layout;
|
||||
GskVulkanUploader *uploader;
|
||||
@ -131,7 +129,6 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
|
||||
self->vulkan = context;
|
||||
self->renderer = renderer;
|
||||
self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
gsk_descriptor_image_infos_init (&self->descriptor_images);
|
||||
gsk_descriptor_image_infos_init (&self->descriptor_samplers);
|
||||
gsk_descriptor_buffer_infos_init (&self->descriptor_buffers);
|
||||
@ -171,46 +168,6 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
NULL,
|
||||
&self->descriptor_pool);
|
||||
|
||||
GSK_VK_CHECK (vkCreateRenderPass, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkRenderPassCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkAttachmentDescription[]) {
|
||||
{
|
||||
.format = gdk_vulkan_context_get_image_format (self->vulkan),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
}
|
||||
},
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = (VkSubpassDescription []) {
|
||||
{
|
||||
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
.inputAttachmentCount = 0,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = 0,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pResolveAttachments = (VkAttachmentReference []) {
|
||||
{
|
||||
.attachment = VK_ATTACHMENT_UNUSED,
|
||||
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
}
|
||||
},
|
||||
.pDepthStencilAttachment = NULL,
|
||||
}
|
||||
},
|
||||
.dependencyCount = 0
|
||||
},
|
||||
NULL,
|
||||
&self->render_pass);
|
||||
|
||||
GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
|
||||
&(VkDescriptorSetLayoutCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
@ -324,58 +281,6 @@ gsk_vulkan_render_new (GskRenderer *renderer,
|
||||
return self;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
VkFramebuffer framebuffer;
|
||||
} HashFramebufferEntry;
|
||||
|
||||
static void
|
||||
gsk_vulkan_render_remove_framebuffer_from_image (gpointer data,
|
||||
GObject *image)
|
||||
{
|
||||
GskVulkanRender *self = data;
|
||||
HashFramebufferEntry *fb;
|
||||
|
||||
fb = g_hash_table_lookup (self->framebuffers, image);
|
||||
g_hash_table_remove (self->framebuffers, image);
|
||||
|
||||
vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan),
|
||||
fb->framebuffer,
|
||||
NULL);
|
||||
|
||||
g_free (fb);
|
||||
}
|
||||
|
||||
VkFramebuffer
|
||||
gsk_vulkan_render_get_framebuffer (GskVulkanRender *self,
|
||||
GskVulkanImage *image)
|
||||
{
|
||||
HashFramebufferEntry *fb;
|
||||
|
||||
fb = g_hash_table_lookup (self->framebuffers, image);
|
||||
if (fb)
|
||||
return fb->framebuffer;
|
||||
|
||||
fb = g_new0 (HashFramebufferEntry, 1);
|
||||
GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkFramebufferCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = self->render_pass,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkImageView[1]) {
|
||||
gsk_vulkan_image_get_image_view (image)
|
||||
},
|
||||
.width = gsk_vulkan_image_get_width (image),
|
||||
.height = gsk_vulkan_image_get_height (image),
|
||||
.layers = 1
|
||||
},
|
||||
NULL,
|
||||
&fb->framebuffer);
|
||||
g_hash_table_insert (self->framebuffers, image, fb);
|
||||
g_object_weak_ref (G_OBJECT (image), gsk_vulkan_render_remove_framebuffer_from_image, self);
|
||||
|
||||
return fb->framebuffer;
|
||||
}
|
||||
|
||||
VkFence
|
||||
gsk_vulkan_render_get_fence (GskVulkanRender *self)
|
||||
{
|
||||
@ -441,7 +346,8 @@ gsk_vulkan_render_upload (GskVulkanRender *self)
|
||||
|
||||
GskVulkanPipeline *
|
||||
gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
GskVulkanPipelineType type)
|
||||
GskVulkanPipelineType type,
|
||||
VkRenderPass render_pass)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
@ -492,7 +398,7 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
self->pipelines[type] = pipeline_info[type].create_func (self->vulkan,
|
||||
self->pipeline_layout,
|
||||
pipeline_info[type].name,
|
||||
self->render_pass);
|
||||
render_pass);
|
||||
|
||||
return self->pipelines[type];
|
||||
}
|
||||
@ -640,6 +546,7 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
|
||||
{
|
||||
gsk_vulkan_buffer_unmap (self->storage_buffer);
|
||||
self->storage_buffer_memory = NULL;
|
||||
self->storage_buffer_used = 0;
|
||||
}
|
||||
|
||||
GSK_VK_CHECK (vkAllocateDescriptorSets, device,
|
||||
@ -810,8 +717,6 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
|
||||
void
|
||||
gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
VkDevice device;
|
||||
guint i;
|
||||
|
||||
@ -819,20 +724,6 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
|
||||
device = gdk_vulkan_context_get_device (self->vulkan);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->framebuffers);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
HashFramebufferEntry *fb = value;
|
||||
|
||||
vkDestroyFramebuffer (gdk_vulkan_context_get_device (self->vulkan),
|
||||
fb->framebuffer,
|
||||
NULL);
|
||||
g_free (fb);
|
||||
g_object_weak_unref (G_OBJECT (key), gsk_vulkan_render_remove_framebuffer_from_image, self);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
g_hash_table_unref (self->framebuffers);
|
||||
|
||||
for (i = 0; i < GSK_VULKAN_N_PIPELINES; i++)
|
||||
g_clear_object (&self->pipelines[i]);
|
||||
|
||||
@ -843,10 +734,6 @@ gsk_vulkan_render_free (GskVulkanRender *self)
|
||||
self->pipeline_layout,
|
||||
NULL);
|
||||
|
||||
vkDestroyRenderPass (device,
|
||||
self->render_pass,
|
||||
NULL);
|
||||
|
||||
vkDestroyDescriptorPool (device,
|
||||
self->descriptor_pool,
|
||||
NULL);
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "gskvulkanrenderprivate.h"
|
||||
#include "gskvulkanglyphcacheprivate.h"
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkdrawcontextprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
@ -139,20 +141,23 @@ static void
|
||||
gsk_vulkan_renderer_update_images_cb (GdkVulkanContext *context,
|
||||
GskVulkanRenderer *self)
|
||||
{
|
||||
GdkSurface *window;
|
||||
GdkSurface *surface;
|
||||
double scale;
|
||||
gsize width, height;
|
||||
guint i;
|
||||
|
||||
surface = gsk_renderer_get_surface (GSK_RENDERER (self));
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
gsk_vulkan_renderer_free_targets (self);
|
||||
|
||||
self->n_targets = gdk_vulkan_context_get_n_images (context);
|
||||
self->targets = g_new (GskVulkanImage *, self->n_targets);
|
||||
|
||||
window = gsk_renderer_get_surface (GSK_RENDERER (self));
|
||||
scale = gdk_surface_get_scale (window);
|
||||
width = (int) ceil (gdk_surface_get_width (window) * scale);
|
||||
height = (int) ceil (gdk_surface_get_height (window) * scale);
|
||||
scale = gdk_surface_get_scale (surface);
|
||||
width = (int) ceil (gdk_surface_get_width (surface) * scale);
|
||||
height = (int) ceil (gdk_surface_get_height (surface) * scale);
|
||||
|
||||
for (i = 0; i < self->n_targets; i++)
|
||||
{
|
||||
@ -203,13 +208,10 @@ gsk_vulkan_renderer_realize (GskRenderer *renderer,
|
||||
GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"The Vulkan renderer does not support surfaceless rendering yet.");
|
||||
return FALSE;
|
||||
}
|
||||
self->vulkan = gdk_display_create_vulkan_context (gdk_display_get_default (), error);
|
||||
else
|
||||
self->vulkan = gdk_surface_create_vulkan_context (surface, error);
|
||||
|
||||
self->vulkan = gdk_surface_create_vulkan_context (surface, error);
|
||||
if (self->vulkan == NULL)
|
||||
return FALSE;
|
||||
|
||||
@ -283,9 +285,10 @@ gsk_vulkan_renderer_render_texture (GskRenderer *renderer,
|
||||
viewport->origin.y,
|
||||
ceil (viewport->size.width),
|
||||
ceil (viewport->size.height));
|
||||
image = gsk_vulkan_image_new_for_framebuffer (self->vulkan,
|
||||
rounded_viewport.size.width,
|
||||
rounded_viewport.size.height);
|
||||
image = gsk_vulkan_image_new_for_offscreen (self->vulkan,
|
||||
gsk_render_node_get_preferred_vulkan_format (root),
|
||||
rounded_viewport.size.width,
|
||||
rounded_viewport.size.height);
|
||||
|
||||
gsk_vulkan_render_reset (render, image, &rounded_viewport, NULL);
|
||||
gsk_vulkan_render_add_node (render, root);
|
||||
@ -339,7 +342,9 @@ gsk_vulkan_renderer_render (GskRenderer *renderer,
|
||||
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
|
||||
#endif
|
||||
|
||||
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->vulkan), region);
|
||||
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->vulkan),
|
||||
gsk_render_node_get_preferred_depth (root),
|
||||
region);
|
||||
render = gsk_vulkan_renderer_get_render (self);
|
||||
|
||||
render_region = get_render_region (self);
|
||||
|
@ -50,5 +50,5 @@ GskRenderer * gsk_vulkan_renderer_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GDK_WINDOWING_VULKAN */
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
|
||||
|
@ -136,6 +136,7 @@ struct _GskVulkanRenderPass
|
||||
graphene_vec2_t scale;
|
||||
|
||||
VkRenderPass render_pass;
|
||||
VkFramebuffer framebuffer;
|
||||
VkSemaphore signal_semaphore;
|
||||
GArray *wait_semaphores;
|
||||
GskVulkanBuffer *vertex_data;
|
||||
@ -186,7 +187,7 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkAttachmentDescription[]) {
|
||||
{
|
||||
.format = gdk_vulkan_context_get_image_format (self->vulkan),
|
||||
.format = gsk_vulkan_image_get_vk_format (target),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
@ -220,6 +221,21 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
NULL,
|
||||
&self->render_pass);
|
||||
|
||||
GSK_VK_CHECK (vkCreateFramebuffer, gdk_vulkan_context_get_device (self->vulkan),
|
||||
&(VkFramebufferCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||
.renderPass = self->render_pass,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = (VkImageView[1]) {
|
||||
gsk_vulkan_image_get_image_view (target)
|
||||
},
|
||||
.width = gsk_vulkan_image_get_width (target),
|
||||
.height = gsk_vulkan_image_get_height (target),
|
||||
.layers = 1
|
||||
},
|
||||
NULL,
|
||||
&self->framebuffer);
|
||||
|
||||
self->signal_semaphore = signal_semaphore;
|
||||
self->wait_semaphores = g_array_new (FALSE, FALSE, sizeof (VkSemaphore));
|
||||
self->vertex_data = NULL;
|
||||
@ -238,19 +254,19 @@ gsk_vulkan_render_pass_new (GdkVulkanContext *context,
|
||||
void
|
||||
gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
|
||||
{
|
||||
VkDevice device = gdk_vulkan_context_get_device (self->vulkan);
|
||||
|
||||
g_array_unref (self->render_ops);
|
||||
g_object_unref (self->vulkan);
|
||||
g_object_unref (self->target);
|
||||
cairo_region_destroy (self->clip);
|
||||
vkDestroyRenderPass (gdk_vulkan_context_get_device (self->vulkan),
|
||||
self->render_pass,
|
||||
NULL);
|
||||
vkDestroyFramebuffer (device, self->framebuffer, NULL);
|
||||
vkDestroyRenderPass (device, self->render_pass, NULL);
|
||||
|
||||
if (self->vertex_data)
|
||||
gsk_vulkan_buffer_free (self->vertex_data);
|
||||
if (self->signal_semaphore != VK_NULL_HANDLE)
|
||||
vkDestroySemaphore (gdk_vulkan_context_get_device (self->vulkan),
|
||||
self->signal_semaphore,
|
||||
NULL);
|
||||
vkDestroySemaphore (device, self->signal_semaphore, NULL);
|
||||
g_array_unref (self->wait_semaphores);
|
||||
|
||||
g_free (self);
|
||||
@ -297,6 +313,16 @@ gsk_vulkan_render_pass_append_push_constants (GskVulkanRenderPass *self,
|
||||
return FALSE; \
|
||||
}G_STMT_END
|
||||
|
||||
static GskVulkanPipeline *
|
||||
gsk_vulkan_render_pass_get_pipeline (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render,
|
||||
GskVulkanPipelineType pipeline_type)
|
||||
{
|
||||
return gsk_vulkan_render_get_pipeline (render,
|
||||
pipeline_type,
|
||||
self->render_pass);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render,
|
||||
@ -333,7 +359,7 @@ gsk_vulkan_render_pass_add_fallback_node (GskVulkanRenderPass *self,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_TEXTURE);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, GSK_VULKAN_PIPELINE_TEXTURE);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -397,7 +423,7 @@ gsk_vulkan_render_pass_add_color_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -423,7 +449,7 @@ gsk_vulkan_render_pass_add_linear_gradient_node (GskVulkanRenderPass *self
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_LINEAR_GRADIENT_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -449,7 +475,7 @@ gsk_vulkan_render_pass_add_border_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -475,7 +501,7 @@ gsk_vulkan_render_pass_add_texture_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -501,7 +527,7 @@ gsk_vulkan_render_pass_add_texture_scale_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -529,7 +555,7 @@ gsk_vulkan_render_pass_add_inset_shadow_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_INSET_SHADOW_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -557,7 +583,7 @@ gsk_vulkan_render_pass_add_outset_shadow_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -737,7 +763,7 @@ gsk_vulkan_render_pass_add_opacity_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -763,7 +789,7 @@ gsk_vulkan_render_pass_add_color_matrix_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -933,7 +959,7 @@ gsk_vulkan_render_pass_add_repeat_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_TEXTURE_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -959,7 +985,7 @@ gsk_vulkan_render_pass_add_blend_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_BLEND_MODE_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -985,7 +1011,7 @@ gsk_vulkan_render_pass_add_cross_fade_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_CROSS_FADE_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -1036,7 +1062,7 @@ gsk_vulkan_render_pass_add_text_node (GskVulkanRenderPass *self,
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED;
|
||||
op.type = GSK_VULKAN_OP_TEXT;
|
||||
}
|
||||
op.text.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.text.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
|
||||
op.text.start_glyph = 0;
|
||||
op.text.texture_index = G_MAXUINT;
|
||||
@ -1100,7 +1126,7 @@ gsk_vulkan_render_pass_add_blur_node (GskVulkanRenderPass *self,
|
||||
else
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_BLUR_CLIP_ROUNDED;
|
||||
|
||||
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||
op.render.pipeline = gsk_vulkan_render_pass_get_pipeline (self, render, pipeline_type);
|
||||
g_array_append_val (self->render_ops, op);
|
||||
|
||||
return TRUE;
|
||||
@ -1249,6 +1275,7 @@ gsk_vulkan_render_pass_render_offscreen (GdkVulkanContext *vulkan,
|
||||
ceil (scale_y * viewport->size.height));
|
||||
|
||||
result = gsk_vulkan_image_new_for_offscreen (vulkan,
|
||||
gsk_render_node_get_preferred_vulkan_format (node),
|
||||
view.size.width, view.size.height);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
@ -1368,8 +1395,8 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
|
||||
width = ceil (node->bounds.size.width * graphene_vec2_get_x (scale));
|
||||
height = ceil (node->bounds.size.height * graphene_vec2_get_y (scale));
|
||||
|
||||
result = gsk_vulkan_image_new_for_upload (uploader, width, height);
|
||||
gsk_vulkan_image_map_memory (result, uploader, &map);
|
||||
result = gsk_vulkan_image_new_for_upload (uploader, GDK_MEMORY_DEFAULT, width, height);
|
||||
gsk_vulkan_image_map_memory (result, uploader, GSK_VULKAN_WRITE, &map);
|
||||
surface = cairo_image_surface_create_for_data (map.data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width, height,
|
||||
@ -1429,8 +1456,8 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
|
||||
width = ceil (node->bounds.size.width * graphene_vec2_get_x (&self->scale));
|
||||
height = ceil (node->bounds.size.height * graphene_vec2_get_y (&self->scale));
|
||||
|
||||
op->source = gsk_vulkan_image_new_for_upload (uploader, width, height);
|
||||
gsk_vulkan_image_map_memory (op->source, uploader, &map);
|
||||
op->source = gsk_vulkan_image_new_for_upload (uploader, GDK_MEMORY_DEFAULT, width, height);
|
||||
gsk_vulkan_image_map_memory (op->source, uploader, GSK_VULKAN_WRITE, &map);
|
||||
surface = cairo_image_surface_create_for_data (map.data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width, height,
|
||||
@ -2430,7 +2457,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
||||
&(VkRenderPassBeginInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = self->render_pass,
|
||||
.framebuffer = gsk_vulkan_render_get_framebuffer (render, self->target),
|
||||
.framebuffer = self->framebuffer,
|
||||
.renderArea = {
|
||||
{ rect.x, rect.y },
|
||||
{ rect.width, rect.height }
|
||||
|
@ -81,7 +81,8 @@ void gsk_vulkan_render_add_render_pass (GskVulk
|
||||
void gsk_vulkan_render_upload (GskVulkanRender *self);
|
||||
|
||||
GskVulkanPipeline * gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
GskVulkanPipelineType pipeline_type);
|
||||
GskVulkanPipelineType pipeline_type,
|
||||
VkRenderPass render_pass);
|
||||
gsize gsk_vulkan_render_get_sampler_descriptor (GskVulkanRender *self,
|
||||
GskVulkanRenderSampler render_sampler);
|
||||
gsize gsk_vulkan_render_get_image_descriptor (GskVulkanRender *self,
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gsk/gl/gskglrenderer.h"
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include "gsk/vulkan/gskvulkanrenderer.h"
|
||||
#endif
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@ -8,6 +11,7 @@
|
||||
|
||||
static GdkGLContext *gl_context = NULL;
|
||||
static GskRenderer *gl_renderer = NULL;
|
||||
static GskRenderer *vulkan_renderer = NULL;
|
||||
|
||||
typedef struct _TextureBuilder TextureBuilder;
|
||||
|
||||
@ -16,6 +20,7 @@ typedef enum {
|
||||
TEXTURE_METHOD_GL,
|
||||
TEXTURE_METHOD_GL_RELEASED,
|
||||
TEXTURE_METHOD_GL_NATIVE,
|
||||
TEXTURE_METHOD_VULKAN,
|
||||
TEXTURE_METHOD_PNG,
|
||||
TEXTURE_METHOD_PNG_PIXBUF,
|
||||
TEXTURE_METHOD_TIFF,
|
||||
@ -431,7 +436,7 @@ encode (GdkMemoryFormat format,
|
||||
return GSIZE_TO_POINTER (method * GDK_MEMORY_N_FORMATS + format);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
decode (gconstpointer data,
|
||||
GdkMemoryFormat *format,
|
||||
TextureMethod *method)
|
||||
@ -442,14 +447,6 @@ decode (gconstpointer data,
|
||||
value /= GDK_MEMORY_N_FORMATS;
|
||||
|
||||
*method = value;
|
||||
|
||||
if (*method == TEXTURE_METHOD_TIFF_PIXBUF)
|
||||
{
|
||||
g_test_skip ("the pixbuf tiff loader is broken (gdk-pixbuf#100)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
@ -805,13 +802,17 @@ compare_textures (GdkTexture *texture1,
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
upload_to_gl (GdkTexture *texture)
|
||||
upload_to_renderer (GdkTexture *texture,
|
||||
GskRenderer *renderer)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
GdkTexture *result;
|
||||
|
||||
if (gl_renderer == NULL)
|
||||
return texture;
|
||||
if (renderer == NULL)
|
||||
{
|
||||
g_test_skip ("renderer not supported");
|
||||
return texture;
|
||||
}
|
||||
|
||||
node = gsk_texture_node_new (texture,
|
||||
&GRAPHENE_RECT_INIT(
|
||||
@ -819,7 +820,7 @@ upload_to_gl (GdkTexture *texture)
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture)
|
||||
));
|
||||
result = gsk_renderer_render_texture (gl_renderer, node, NULL);
|
||||
result = gsk_renderer_render_texture (renderer, node, NULL);
|
||||
gsk_render_node_unref (node);
|
||||
g_object_unref (texture);
|
||||
|
||||
@ -910,7 +911,7 @@ upload_to_gl_native (GdkTexture *texture)
|
||||
return result;
|
||||
}
|
||||
|
||||
return upload_to_gl (texture);
|
||||
return upload_to_renderer (texture, gl_renderer);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
@ -934,11 +935,11 @@ create_texture (GdkMemoryFormat format,
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_GL:
|
||||
texture = upload_to_gl (texture);
|
||||
texture = upload_to_renderer (texture, gl_renderer);
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_GL_RELEASED:
|
||||
texture = upload_to_gl (texture);
|
||||
texture = upload_to_renderer (texture, gl_renderer);
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
gdk_gl_texture_release (GDK_GL_TEXTURE (texture));
|
||||
break;
|
||||
@ -947,6 +948,10 @@ create_texture (GdkMemoryFormat format,
|
||||
texture = upload_to_gl_native (texture);
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_VULKAN:
|
||||
texture = upload_to_renderer (texture, vulkan_renderer);
|
||||
break;
|
||||
|
||||
case TEXTURE_METHOD_PNG:
|
||||
{
|
||||
GBytes *bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
@ -1030,6 +1035,7 @@ texture_method_is_accurate (TextureMethod method)
|
||||
case TEXTURE_METHOD_GL:
|
||||
case TEXTURE_METHOD_GL_RELEASED:
|
||||
case TEXTURE_METHOD_GL_NATIVE:
|
||||
case TEXTURE_METHOD_VULKAN:
|
||||
case TEXTURE_METHOD_PNG:
|
||||
case TEXTURE_METHOD_PNG_PIXBUF:
|
||||
case TEXTURE_METHOD_TIFF_PIXBUF:
|
||||
@ -1123,22 +1129,66 @@ static gboolean
|
||||
should_skip_download_test (GdkMemoryFormat format,
|
||||
TextureMethod method)
|
||||
{
|
||||
int major, minor;
|
||||
switch (method)
|
||||
{
|
||||
case TEXTURE_METHOD_LOCAL:
|
||||
case TEXTURE_METHOD_PNG:
|
||||
case TEXTURE_METHOD_PNG_PIXBUF:
|
||||
case TEXTURE_METHOD_TIFF:
|
||||
return FALSE;
|
||||
|
||||
gdk_gl_context_get_version (gl_context, &major, &minor);
|
||||
case TEXTURE_METHOD_GL:
|
||||
case TEXTURE_METHOD_GL_RELEASED:
|
||||
if (gl_renderer == NULL)
|
||||
{
|
||||
g_test_skip ("OpenGL renderer is not supported");
|
||||
return TRUE;
|
||||
}
|
||||
G_GNUC_FALLTHROUGH;
|
||||
|
||||
if ((method == TEXTURE_METHOD_GL ||
|
||||
method == TEXTURE_METHOD_GL_RELEASED ||
|
||||
method == TEXTURE_METHOD_GL_NATIVE) &&
|
||||
gdk_gl_context_get_use_es (gl_context) &&
|
||||
(major < 3 || (major == 3 && minor < 1)) &&
|
||||
gdk_memory_format_is_deep (format))
|
||||
{
|
||||
g_test_skip ("GLES < 3.1 can't handle 16bit non-RGBA formats");
|
||||
case TEXTURE_METHOD_GL_NATIVE:
|
||||
{
|
||||
int major, minor;
|
||||
|
||||
if (gl_context == NULL)
|
||||
{
|
||||
g_test_skip ("OpenGL is not supported");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gdk_gl_context_get_version (gl_context, &major, &minor);
|
||||
|
||||
if ((method == TEXTURE_METHOD_GL ||
|
||||
method == TEXTURE_METHOD_GL_RELEASED ||
|
||||
method == TEXTURE_METHOD_GL_NATIVE) &&
|
||||
gdk_gl_context_get_use_es (gl_context) &&
|
||||
(major < 3 || (major == 3 && minor < 1)) &&
|
||||
gdk_memory_format_is_deep (format))
|
||||
{
|
||||
g_test_skip ("GLES < 3.1 can't handle 16bit non-RGBA formats");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case TEXTURE_METHOD_VULKAN:
|
||||
if (vulkan_renderer == NULL)
|
||||
{
|
||||
g_test_skip ("Vulkan is not supported");
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case TEXTURE_METHOD_TIFF_PIXBUF:
|
||||
g_test_skip ("the pixbuf tiff loader is broken (gdk-pixbuf#100)");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
case N_TEXTURE_METHODS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1152,8 +1202,7 @@ test_download (gconstpointer data,
|
||||
GdkTexture *expected, *test;
|
||||
gsize i;
|
||||
|
||||
if (!decode (data, &format, &method))
|
||||
return;
|
||||
decode (data, &format, &method);
|
||||
|
||||
if (should_skip_download_test (format, method))
|
||||
return;
|
||||
@ -1168,7 +1217,8 @@ test_download (gconstpointer data,
|
||||
if (color.alpha == 0.f &&
|
||||
!gdk_memory_format_is_premultiplied (format) &&
|
||||
gdk_memory_format_has_alpha (format) &&
|
||||
(method == TEXTURE_METHOD_GL || method == TEXTURE_METHOD_GL_RELEASED || method == TEXTURE_METHOD_GL_NATIVE))
|
||||
(method == TEXTURE_METHOD_GL || method == TEXTURE_METHOD_GL_RELEASED ||
|
||||
method == TEXTURE_METHOD_GL_NATIVE || method == TEXTURE_METHOD_VULKAN))
|
||||
color = (GdkRGBA) { 0, 0, 0, 0 };
|
||||
|
||||
expected = create_texture (format, TEXTURE_METHOD_LOCAL, width, height, &color);
|
||||
@ -1297,7 +1347,7 @@ add_test (const char *name,
|
||||
{
|
||||
for (method = 0; method < N_TEXTURE_METHODS; method++)
|
||||
{
|
||||
const char *method_names[N_TEXTURE_METHODS] = { "local", "gl", "gl-released", "gl-native", "png", "png-pixbuf", "tiff", "tiff-pixbuf" };
|
||||
const char *method_names[N_TEXTURE_METHODS] = { "local", "gl", "gl-released", "gl-native", "vulkan", "png", "png-pixbuf", "tiff", "tiff-pixbuf" };
|
||||
char *test_name = g_strdup_printf ("%s/%s/%s",
|
||||
name,
|
||||
g_enum_get_value (enum_class, format)->value_nick,
|
||||
@ -1344,7 +1394,7 @@ main (int argc, char *argv[])
|
||||
add_conversion_test ("/memorytexture/conversion_random", test_conversion_random);
|
||||
|
||||
gl_context = gdk_display_create_gl_context (gdk_display_get_default (), NULL);
|
||||
if (!gdk_gl_context_realize (gl_context, NULL))
|
||||
if (gl_context == NULL || !gdk_gl_context_realize (gl_context, NULL))
|
||||
{
|
||||
g_clear_object (&gl_context);
|
||||
}
|
||||
@ -1355,8 +1405,23 @@ main (int argc, char *argv[])
|
||||
g_clear_object (&gl_renderer);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
vulkan_renderer = gsk_vulkan_renderer_new ();
|
||||
if (!gsk_renderer_realize (vulkan_renderer, NULL, NULL))
|
||||
{
|
||||
g_clear_object (&vulkan_renderer);
|
||||
}
|
||||
#endif
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
if (vulkan_renderer)
|
||||
{
|
||||
gsk_renderer_unrealize (vulkan_renderer);
|
||||
g_clear_object (&vulkan_renderer);
|
||||
}
|
||||
#endif
|
||||
if (gl_renderer)
|
||||
{
|
||||
gsk_renderer_unrealize (gl_renderer);
|
||||
|
Loading…
Reference in New Issue
Block a user