diff --git a/gdk/win32/gdkd3d12texture.c b/gdk/win32/gdkd3d12texture.c index ce8fe2eb68..3b4d30dff9 100644 --- a/gdk/win32/gdkd3d12texture.c +++ b/gdk/win32/gdkd3d12texture.c @@ -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", diff --git a/gdk/win32/gdkd3d12texturebuilder.c b/gdk/win32/gdkd3d12texturebuilder.c index 66df70d171..2f2bfc415a 100644 --- a/gdk/win32/gdkd3d12texturebuilder.c +++ b/gdk/win32/gdkd3d12texturebuilder.c @@ -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` diff --git a/gdk/win32/gdkd3d12texturebuilder.h b/gdk/win32/gdkd3d12texturebuilder.h index f3a4eff7fc..1bd4625d42 100644 --- a/gdk/win32/gdkd3d12texturebuilder.h +++ b/gdk/win32/gdkd3d12texturebuilder.h @@ -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