wined3d: Introduce an API for creating an identity SRV on a texture.

This commit is contained in:
Zebediah Figura 2022-12-30 18:13:57 -06:00 committed by Alexandre Julliard
parent d8782a9b8e
commit 1698fd40cd
6 changed files with 73 additions and 5 deletions

View file

@ -1648,6 +1648,12 @@ ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture)
{
bool in_cs_thread = GetCurrentThreadId() == texture->resource.device->cs->thread_id;
if (texture->identity_srv)
{
assert(!in_cs_thread);
wined3d_shader_resource_view_destroy(texture->identity_srv);
}
/* This is called from the CS thread to destroy temporary textures. */
if (!in_cs_thread)
wined3d_mutex_lock();
@ -4667,6 +4673,42 @@ void wined3d_texture_update_sub_resource(struct wined3d_texture *texture, unsign
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
}
struct wined3d_shader_resource_view * CDECL wined3d_texture_acquire_identity_srv(struct wined3d_texture *texture)
{
struct wined3d_view_desc desc;
HRESULT hr;
TRACE("texture %p.\n", texture);
if (texture->identity_srv)
return texture->identity_srv;
desc.format_id = texture->resource.format->id;
/* The texture owns a reference to the SRV, so we can't have the SRV hold
* a reference to the texture.
* At the same time, a view must be destroyed before its texture, and we
* need a bound SRV to keep the texture alive even if it doesn't have any
* other references.
* In order to achieve this we have the objects share reference counts.
* This means the view doesn't hold a reference to the resource, but any
* references to the view are forwarded to the resource instead. The view
* is destroyed manually when all references are released. */
desc.flags = WINED3D_VIEW_FORWARD_REFERENCE;
desc.u.texture.level_idx = 0;
desc.u.texture.level_count = texture->level_count;
desc.u.texture.layer_idx = 0;
desc.u.texture.layer_count = texture->layer_count;
if (FAILED(hr = wined3d_shader_resource_view_create(&desc, &texture->resource,
NULL, &wined3d_null_parent_ops, &texture->identity_srv)))
{
ERR("Failed to create shader resource view, hr %#lx.\n", hr);
return NULL;
}
wined3d_shader_resource_view_decref(texture->identity_srv);
return texture->identity_srv;
}
static void wined3d_texture_no3d_upload_data(struct wined3d_context *context,
const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format,
const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch,

View file

@ -4918,6 +4918,7 @@ const char *wined3d_debug_view_desc(const struct wined3d_view_desc *d, const str
VIEW_FLAG_TO_STR(WINED3D_VIEW_TEXTURE_ARRAY);
VIEW_FLAG_TO_STR(WINED3D_VIEW_READ_ONLY_DEPTH);
VIEW_FLAG_TO_STR(WINED3D_VIEW_READ_ONLY_STENCIL);
VIEW_FLAG_TO_STR(WINED3D_VIEW_FORWARD_REFERENCE);
#undef VIEW_FLAG_TO_STR
if (flags)
FIXME("Unrecognised view flag(s) %#x.\n", flags);

View file

@ -959,8 +959,12 @@ HRESULT CDECL wined3d_rendertarget_view_create_from_sub_resource(struct wined3d_
ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_view *view)
{
unsigned int refcount = InterlockedIncrement(&view->refcount);
unsigned int refcount;
if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE)
return wined3d_resource_incref(view->resource);
refcount = InterlockedIncrement(&view->refcount);
TRACE("%p increasing refcount to %u.\n", view, refcount);
return refcount;
@ -971,10 +975,21 @@ void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *v
view->parent_ops->wined3d_object_destroyed(view->parent);
}
void wined3d_shader_resource_view_destroy(struct wined3d_shader_resource_view *view)
{
wined3d_mutex_lock();
view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
wined3d_mutex_unlock();
}
ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view)
{
unsigned int refcount = InterlockedDecrement(&view->refcount);
unsigned int refcount;
if (view->desc.flags & WINED3D_VIEW_FORWARD_REFERENCE)
return wined3d_resource_decref(view->resource);
refcount = InterlockedDecrement(&view->refcount);
TRACE("%p decreasing refcount to %u.\n", view, refcount);
if (!refcount)
@ -986,9 +1001,7 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
* device, which the resource implicitly provides.
* - We shouldn't free buffer resources until after we've removed the
* view from its bo_user list. */
wined3d_mutex_lock();
resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view);
wined3d_mutex_unlock();
wined3d_shader_resource_view_destroy(view);
wined3d_resource_decref(resource);
}
@ -1091,6 +1104,10 @@ static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_
return E_INVALIDARG;
view->desc = *desc;
/* If WINED3D_VIEW_FORWARD_REFERENCE, the view shouldn't take a reference
* to the resource. However, the reference to the view returned by this
* function should translate to a resource reference, so we increment the
* resource's reference count anyway. */
wined3d_resource_incref(view->resource = resource);
return WINED3D_OK;

View file

@ -298,6 +298,7 @@
@ cdecl wined3d_swapchain_state_resize_target(ptr ptr)
@ cdecl wined3d_swapchain_state_set_fullscreen(ptr ptr ptr)
@ cdecl wined3d_texture_acquire_identity_srv(ptr)
@ cdecl wined3d_texture_add_dirty_region(ptr long ptr)
@ cdecl wined3d_texture_create(ptr ptr long long long ptr ptr ptr ptr)
@ cdecl wined3d_texture_decref(ptr)

View file

@ -3335,6 +3335,8 @@ struct wined3d_texture
unsigned int row_pitch;
unsigned int slice_pitch;
struct wined3d_shader_resource_view *identity_srv;
/* May only be accessed from the command stream worker thread. */
struct wined3d_texture_async
{
@ -3935,6 +3937,7 @@ struct wined3d_shader_resource_view
};
void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view);
void wined3d_shader_resource_view_destroy(struct wined3d_shader_resource_view *view);
static inline struct wined3d_texture *wined3d_state_get_ffp_texture(const struct wined3d_state *state, unsigned int idx)
{

View file

@ -1583,6 +1583,9 @@ enum wined3d_memory_segment_group
#define WINED3D_VIEW_TEXTURE_ARRAY 0x00000010
#define WINED3D_VIEW_READ_ONLY_DEPTH 0x00000020
#define WINED3D_VIEW_READ_ONLY_STENCIL 0x00000040
/* The view shares a reference count with its resource.
* See wined3d_texture_acquire_identity_srv(). */
#define WINED3D_VIEW_FORWARD_REFERENCE 0x00000080
#define WINED3D_MAX_VIEWPORTS 16
@ -2866,6 +2869,7 @@ HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_s
HRESULT __cdecl wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *desc, const struct wined3d_display_mode *mode);
struct wined3d_shader_resource_view * __cdecl wined3d_texture_acquire_identity_srv(struct wined3d_texture *texture);
HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
UINT layer, const struct wined3d_box *dirty_region);
HRESULT __cdecl wined3d_texture_create(struct wined3d_device *device, const struct wined3d_resource_desc *desc,