win32: Add GdkD3D12TextureBuilder::fence

Add ::fence and ::fence-wait to set the fence and the value to wait for.

And wait for it before download()ing.
This commit is contained in:
Benjamin Otte
2024-11-06 23:31:51 +01:00
parent b5c0dc1ced
commit ac066e1807
3 changed files with 174 additions and 3 deletions

View File

@@ -49,6 +49,9 @@ struct _GdkD3D12Texture
ID3D12Resource *resource;
HANDLE resource_handle;
ID3D12Fence *fence;
HANDLE fence_handle;
guint64 fence_wait;
GDestroyNotify destroy;
gpointer data;
@@ -75,18 +78,27 @@ gdk_d3d12_texture_dispose (GObject *object)
{
GdkD3D12Texture *self = GDK_D3D12_TEXTURE (object);
if (self->fence_handle)
{
if (G_UNLIKELY (!CloseHandle (self->fence_handle)))
{
g_warning ("Failed to fence handle: %s", g_win32_error_message (GetLastError ()));
}
self->fence_handle = NULL;
}
if (self->resource_handle)
{
if (G_UNLIKELY (!CloseHandle (self->resource_handle)))
{
g_warning ("Failed to close handle: %s", g_win32_error_message (GetLastError ()));
g_warning ("Failed to close resource handle: %s", g_win32_error_message (GetLastError ()));
}
self->resource_handle = NULL;
}
gdk_win32_com_clear (&self->fence);
gdk_win32_com_clear (&self->resource);
if (self->destroy)
if (self->destroy)
{
self->destroy (self->data);
self->destroy = NULL;
@@ -222,6 +234,10 @@ gdk_d3d12_texture_download (GdkTexture *texture,
}),
NULL);
hr_return_if_fail (ID3D12GraphicsCommandList_Close (commands));
if (self->fence)
ID3D12CommandQueue_Wait (queue, self->fence, self->fence_wait);
ID3D12CommandQueue_ExecuteCommandLists (queue, 1, (ID3D12CommandList **) &commands);
#define FENCE_SIGNAL 1
@@ -285,10 +301,12 @@ gdk_d3d12_texture_new_from_builder (GdkD3D12TextureBuilder *builder,
GdkColorState *color_state;
GdkMemoryFormat format;
ID3D12Resource *resource;
ID3D12Fence *fence;
D3D12_RESOURCE_DESC desc;
gboolean premultiplied;
resource = gdk_d3d12_texture_builder_get_resource (builder);
fence = gdk_d3d12_texture_builder_get_fence (builder);
premultiplied = gdk_d3d12_texture_builder_get_premultiplied (builder);
ID3D12Resource_GetDesc (resource, &desc);
@@ -325,6 +343,12 @@ gdk_d3d12_texture_new_from_builder (GdkD3D12TextureBuilder *builder,
GDK_TEXTURE (self)->format = format;
ID3D12Resource_AddRef (resource);
self->resource = resource;
if (fence)
{
ID3D12Fence_AddRef (fence);
self->fence = fence;
self->fence_wait = gdk_d3d12_texture_builder_get_fence_wait (builder);
}
GDK_DEBUG (D3D12,
"Creating %ux%u D3D12 texture, format %u",

View File

@@ -33,6 +33,8 @@ struct _GdkD3D12TextureBuilder
GObject parent_instance;
ID3D12Resource *resource;
ID3D12Fence *fence;
guint64 fence_wait;
GdkColorState *color_state;
gboolean premultiplied;
@@ -69,6 +71,8 @@ enum
{
PROP_0,
PROP_COLOR_STATE,
PROP_FENCE,
PROP_FENCE_WAIT,
PROP_RESOURCE,
PROP_PREMULTIPLIED,
PROP_UPDATE_REGION,
@@ -91,6 +95,7 @@ gdk_d3d12_texture_builder_dispose (GObject *object)
g_clear_pointer (&self->color_state, gdk_color_state_unref);
gdk_win32_com_clear (&self->resource);
gdk_win32_com_clear (&self->fence);
G_OBJECT_CLASS (gdk_d3d12_texture_builder_parent_class)->dispose (object);
}
@@ -109,6 +114,14 @@ gdk_d3d12_texture_builder_get_property (GObject *object,
g_value_set_boxed (value, self->color_state);
break;
case PROP_FENCE:
g_value_set_pointer (value, self->fence);
break;
case PROP_FENCE_WAIT:
g_value_set_uint64 (value, self->fence_wait);
break;
case PROP_PREMULTIPLIED:
g_value_set_boolean (value, self->premultiplied);
break;
@@ -145,6 +158,14 @@ gdk_d3d12_texture_builder_set_property (GObject *object,
gdk_d3d12_texture_builder_set_color_state (self, g_value_get_boxed (value));
break;
case PROP_FENCE:
gdk_d3d12_texture_builder_set_fence (self, g_value_get_pointer (value));
break;
case PROP_FENCE_WAIT:
gdk_d3d12_texture_builder_set_fence_wait (self, g_value_get_uint64 (value));
break;
case PROP_PREMULTIPLIED:
gdk_d3d12_texture_builder_set_premultiplied (self, g_value_get_boolean (value));
break;
@@ -188,6 +209,29 @@ gdk_d3d12_texture_builder_class_init (GdkD3D12TextureBuilderClass *klass)
GDK_TYPE_COLOR_STATE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkD3D12TextureBuilder:fence:
*
* The optional `ID3D12Fence` to wait on before using the resource.
*
* Since: 4.18
*/
properties[PROP_FENCE] =
g_param_spec_pointer ("fence", NULL, NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkD3D12TextureBuilder:fence-wait:
*
* The value the fence should wait on
*
* Since: 4.18
*/
properties[PROP_FENCE_WAIT] =
g_param_spec_uint64 ("fence-wait", NULL, NULL,
0, G_MAXUINT64, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkD3D12TextureBuilder:premultiplied:
*
@@ -308,6 +352,97 @@ gdk_d3d12_texture_builder_set_resource (GdkD3D12TextureBuilder *self,
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RESOURCE]);
}
/**
* gdk_d3d12_texture_builder_get_fence:
* @self: a `GdkD3D12TextureBuilder`
*
* Returns the fence that this texture builder is
* associated with.
*
* Returns: (nullable) (transfer none): the fence
*
* Since: 4.18
*/
ID3D12Fence *
gdk_d3d12_texture_builder_get_fence (GdkD3D12TextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), NULL);
return self->fence;
}
/**
* gdk_d3d12_texture_builder_set_fence:
* @self: a `GdkD3D12TextureBuilder`
* @fence: the fence
*
* Sets the fence that this texture builder is going to construct
* a texture for.
*
* Since: 4.18
*/
void
gdk_d3d12_texture_builder_set_fence (GdkD3D12TextureBuilder *self,
ID3D12Fence *fence)
{
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
if (self->fence == fence)
return;
if (fence)
ID3D12Fence_AddRef (fence);
gdk_win32_com_clear (&self->fence);
self->fence = fence;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FENCE]);
}
/**
* gdk_d3d12_texture_builder_get_fence_wait:
* @self: a `GdkD3D12TextureBuilder`
*
* Returns the value that GTK should wait for on the fence
* before using the resource.
*
* Returns: the fence wait value
*
* Since: 4.18
*/
guint64
gdk_d3d12_texture_builder_get_fence_wait (GdkD3D12TextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self), 0);
return self->fence_wait;
}
/**
* gdk_d3d12_texture_builder_set_fence_wait:
* @self: a `GdkD3D12TextureBuilder`
* @fence_wait: the value to wait on
*
* Sets the value that GTK should wait on on the given fence before using the
* resource.
*
* When no fence is set, this value has no effect.
*
* Since: 4.18
*/
void
gdk_d3d12_texture_builder_set_fence_wait (GdkD3D12TextureBuilder *self,
guint64 fence_wait)
{
g_return_if_fail (GDK_IS_D3D12_TEXTURE_BUILDER (self));
if (self->fence_wait == fence_wait)
return;
self->fence_wait = fence_wait;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FENCE_WAIT]);
}
/**
* gdk_d3d12_texture_builder_get_premultiplied:
* @self: a `GdkD3D12TextureBuilder`

View File

@@ -43,7 +43,19 @@ ID3D12Resource * gdk_d3d12_texture_builder_get_resource (GdkD3D1
GDK_AVAILABLE_IN_4_18
void gdk_d3d12_texture_builder_set_resource (GdkD3D12TextureBuilder *self,
ID3D12Resource *resource);
GDK_AVAILABLE_IN_4_18
ID3D12Fence * gdk_d3d12_texture_builder_get_fence (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_18
void gdk_d3d12_texture_builder_set_fence (GdkD3D12TextureBuilder *self,
ID3D12Fence *fence);
GDK_AVAILABLE_IN_4_18
guint64 gdk_d3d12_texture_builder_get_fence_wait (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_18
void gdk_d3d12_texture_builder_set_fence_wait (GdkD3D12TextureBuilder *self,
guint64 fence_wait);
GDK_AVAILABLE_IN_4_18
gboolean gdk_d3d12_texture_builder_get_premultiplied (GdkD3D12TextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_18