-- v4: wined3d: Set d3d 1-9 textures in the state as SRVs. d3d9: Use wined3d_texture_acquire_identity_srv(). wined3d: Introduce an API for creating an identity SRV on a texture.
From: Zebediah Figura zfigura@codeweavers.com
Currently we invalidate STATE_SAMPLER whenever an SRV is bound, and hence rely on sampler() to do this for us, which is a bit obscure and won't work with the next patch. --- dlls/wined3d/context_gl.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index bdea2879a51..0cfe26170eb 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -3966,6 +3966,7 @@ void context_state_drawbuf(struct wined3d_context *context, const struct wined3d static void wined3d_context_gl_bind_shader_resources(struct wined3d_context_gl *context_gl, const struct wined3d_state *state, enum wined3d_shader_type shader_type) { + const struct wined3d_gl_info *gl_info = context_gl->gl_info; unsigned int bind_idx, shader_sampler_count, base, count, i; const struct wined3d_device *device = context_gl->c.device; struct wined3d_shader_sampler_map_entry *entry; @@ -3993,18 +3994,23 @@ static void wined3d_context_gl_bind_shader_resources(struct wined3d_context_gl * if (tex_unit_map) bind_idx = tex_unit_map[bind_idx];
- if (!(view = state->shader_resource_view[shader_type][entry->resource_idx])) + if ((view = state->shader_resource_view[shader_type][entry->resource_idx])) + { + if (entry->sampler_idx == WINED3D_SAMPLER_DEFAULT) + sampler = device->default_sampler; + else if (!(sampler = state->sampler[shader_type][entry->sampler_idx])) + sampler = device->null_sampler; + wined3d_shader_resource_view_gl_bind(wined3d_shader_resource_view_gl(view), + bind_idx, wined3d_sampler_gl(sampler), context_gl); + } + else { WARN("No resource view bound at index %u, %u.\n", shader_type, entry->resource_idx); - continue; + wined3d_context_gl_active_texture(context_gl, gl_info, bind_idx); + wined3d_context_gl_bind_texture(context_gl, GL_NONE, 0); + if (gl_info->supported[ARB_SAMPLER_OBJECTS]) + GL_EXTCALL(glBindSampler(bind_idx, 0)); } - - if (entry->sampler_idx == WINED3D_SAMPLER_DEFAULT) - sampler = device->default_sampler; - else if (!(sampler = state->sampler[shader_type][entry->sampler_idx])) - sampler = device->null_sampler; - wined3d_shader_resource_view_gl_bind(wined3d_shader_resource_view_gl(view), - bind_idx, wined3d_sampler_gl(sampler), context_gl); } }
From: Zebediah Figura zfigura@codeweavers.com
Allow us to avoid grabbing a temporary reference. This becomes a problem with the next patch, where we would otherwise grab a reference while a texture is being destroyed, and hence destroy it twice. --- dlls/wined3d/adapter_gl.c | 20 -------------------- dlls/wined3d/adapter_vk.c | 20 -------------------- dlls/wined3d/view.c | 33 +++++++++++++++++++++------------ 3 files changed, 21 insertions(+), 52 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index a103fbe1107..4bc7312ea8f 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4920,12 +4920,8 @@ static void adapter_gl_destroy_rendertarget_view(struct wined3d_rendertarget_vie
TRACE("view_gl %p.\n", view_gl);
- /* Take a reference to the resource, in case releasing the resource - * would cause the device to be destroyed. */ - wined3d_resource_incref(resource); wined3d_rendertarget_view_cleanup(&view_gl->v); wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, NULL, NULL, view_gl); - wined3d_resource_decref(resource); }
static HRESULT adapter_gl_create_shader_resource_view(const struct wined3d_view_desc *desc, @@ -4961,16 +4957,8 @@ static void adapter_gl_destroy_shader_resource_view(struct wined3d_shader_resour
TRACE("view_gl %p.\n", view_gl);
- /* Take a reference to the resource. There are two reasons for this: - * - Releasing the resource could in turn cause the device to be - * destroyed, but we still need the device for - * wined3d_view_vk_destroy(). - * - We shouldn't free buffer resources until after we've removed the - * view from its bo_user list. */ - wined3d_resource_incref(resource); wined3d_shader_resource_view_cleanup(&view_gl->v); wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, NULL, view_gl); - wined3d_resource_decref(resource); }
static HRESULT adapter_gl_create_unordered_access_view(const struct wined3d_view_desc *desc, @@ -5006,16 +4994,8 @@ static void adapter_gl_destroy_unordered_access_view(struct wined3d_unordered_ac
TRACE("view_gl %p.\n", view_gl);
- /* Take a reference to the resource. There are two reasons for this: - * - Releasing the resource could in turn cause the device to be - * destroyed, but we still need the device for - * wined3d_view_vk_destroy(). - * - We shouldn't free buffer resources until after we've removed the - * view from its bo_user list. */ - wined3d_resource_incref(resource); wined3d_unordered_access_view_cleanup(&view_gl->v); wined3d_view_gl_destroy(resource->device, &view_gl->gl_view, &view_gl->bo_user, &view_gl->counter_bo, view_gl); - wined3d_resource_decref(resource); }
static HRESULT adapter_gl_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 96eeeb3472a..d6f4449ce06 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1522,13 +1522,9 @@ static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_vie
TRACE("view_vk %p.\n", view_vk);
- /* Take a reference to the resource, in case releasing the resource - * would cause the device to be destroyed. */ - wined3d_resource_incref(resource); wined3d_rendertarget_view_cleanup(&view_vk->v); wined3d_view_vk_destroy(resource->device, NULL, &view_vk->vk_image_view, NULL, NULL, NULL, &view_vk->command_buffer_id, view_vk); - wined3d_resource_decref(resource); }
static HRESULT adapter_vk_create_shader_resource_view(const struct wined3d_view_desc *desc, @@ -1567,13 +1563,6 @@ static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resour
TRACE("srv_vk %p.\n", srv_vk);
- /* Take a reference to the resource. There are two reasons for this: - * - Releasing the resource could in turn cause the device to be - * destroyed, but we still need the device for - * wined3d_view_vk_destroy(). - * - We shouldn't free buffer resources until after we've removed the - * view from its bo_user list. */ - wined3d_resource_incref(resource); if (resource->type == WINED3D_RTYPE_BUFFER) vk_buffer_view = &view_vk->u.vk_buffer_view; else @@ -1581,7 +1570,6 @@ static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resour wined3d_shader_resource_view_cleanup(&srv_vk->v); wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view, &view_vk->bo_user, NULL, NULL, &view_vk->command_buffer_id, srv_vk); - wined3d_resource_decref(resource); }
static HRESULT adapter_vk_create_unordered_access_view(const struct wined3d_view_desc *desc, @@ -1620,13 +1608,6 @@ static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_ac
TRACE("uav_vk %p.\n", uav_vk);
- /* Take a reference to the resource. There are two reasons for this: - * - Releasing the resource could in turn cause the device to be - * destroyed, but we still need the device for - * wined3d_view_vk_destroy(). - * - We shouldn't free buffer resources until after we've removed the - * view from its bo_user list. */ - wined3d_resource_incref(resource); if (resource->type == WINED3D_RTYPE_BUFFER) vk_buffer_view = &view_vk->u.vk_buffer_view; else @@ -1634,7 +1615,6 @@ static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_ac wined3d_unordered_access_view_cleanup(&uav_vk->v); wined3d_view_vk_destroy(resource->device, vk_buffer_view, vk_image_view, &view_vk->bo_user, &uav_vk->counter_bo, &uav_vk->vk_counter_view, &view_vk->command_buffer_id, uav_vk); - wined3d_resource_decref(resource); }
static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc, diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 4b0ccea7bb2..76b6e66b82e 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -373,10 +373,7 @@ ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *v
void wined3d_rendertarget_view_cleanup(struct wined3d_rendertarget_view *view) { - /* Call wined3d_object_destroyed() before releasing the resource, - * since releasing the resource may end up destroying the parent. */ view->parent_ops->wined3d_object_destroyed(view->parent); - wined3d_resource_decref(view->resource); }
ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view) @@ -387,9 +384,14 @@ ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *v
if (!refcount) { + struct wined3d_resource *resource = view->resource; + + /* Release the resource after destroying the view. + * See wined3d_shader_resource_view_decref(). */ wined3d_mutex_lock(); - view->resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view); + resource->device->adapter->adapter_ops->adapter_destroy_rendertarget_view(view); wined3d_mutex_unlock(); + wined3d_resource_decref(resource); }
return refcount; @@ -966,10 +968,7 @@ ULONG CDECL wined3d_shader_resource_view_incref(struct wined3d_shader_resource_v
void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view) { - /* Call wined3d_object_destroyed() before releasing the resource, - * since releasing the resource may end up destroying the parent. */ view->parent_ops->wined3d_object_destroyed(view->parent); - wined3d_resource_decref(view->resource); }
ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_view *view) @@ -980,9 +979,17 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
if (!refcount) { + struct wined3d_resource *resource = view->resource; + + /* Release the resource after destroying the view: + * - adapter_destroy_shader_resource_view() needs a reference to the + * 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(); - view->resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view); + resource->device->adapter->adapter_ops->adapter_destroy_shader_resource_view(view); wined3d_mutex_unlock(); + wined3d_resource_decref(resource); }
return refcount; @@ -1511,10 +1518,7 @@ ULONG CDECL wined3d_unordered_access_view_incref(struct wined3d_unordered_access
void wined3d_unordered_access_view_cleanup(struct wined3d_unordered_access_view *view) { - /* Call wined3d_object_destroyed() before releasing the resource, - * since releasing the resource may end up destroying the parent. */ view->parent_ops->wined3d_object_destroyed(view->parent); - wined3d_resource_decref(view->resource); }
ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access_view *view) @@ -1525,9 +1529,14 @@ ULONG CDECL wined3d_unordered_access_view_decref(struct wined3d_unordered_access
if (!refcount) { + struct wined3d_resource *resource = view->resource; + + /* Release the resource after destroying the view. + * See wined3d_shader_resource_view_decref(). */ wined3d_mutex_lock(); - view->resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view); + resource->device->adapter->adapter_ops->adapter_destroy_unordered_access_view(view); wined3d_mutex_unlock(); + wined3d_resource_decref(resource); }
return refcount;
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 42 ++++++++++++++++++++++++++++++++++ dlls/wined3d/utils.c | 1 + dlls/wined3d/view.c | 27 ++++++++++++++++++---- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 3 +++ include/wine/wined3d.h | 4 ++++ 6 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 3dfecc949d1..09eea050d9c 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -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, diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 05a0ab36af8..e833bdc8d90 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -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); diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 76b6e66b82e..5174075cdd2 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -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; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 2eaf83160c1..72e0e3fd8fa 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -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) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index bb955873467..429c6632716 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -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) DECLSPEC_HIDDEN; +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) { diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index c2f7950ad3f..d7a3dd1e0fe 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -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,
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d9/d3d9_private.h | 1 - dlls/d3d9/texture.c | 46 ++-------------------------------------- 2 files changed, 2 insertions(+), 45 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index fcd82d2e674..a5f059c5aef 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -222,7 +222,6 @@ struct d3d9_texture struct list rtv_list; DWORD usage; BOOL flags; - struct wined3d_shader_resource_view *wined3d_srv; D3DTEXTUREFILTERTYPE autogen_filter_type; };
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index a3a4dc41272..4de7d2eb99e 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -57,8 +57,6 @@ static ULONG d3d9_texture_decref(struct d3d9_texture *texture) struct d3d9_surface *surface;
wined3d_mutex_lock(); - if (texture->wined3d_srv) - wined3d_shader_resource_view_decref(texture->wined3d_srv); LIST_FOR_EACH_ENTRY(surface, &texture->rtv_list, struct d3d9_surface, rtv_entry) wined3d_rendertarget_view_decref(surface->wined3d_rtv); wined3d_texture_decref(d3d9_texture_get_draw_texture(texture)); @@ -92,56 +90,16 @@ static inline struct d3d9_texture *impl_from_IDirect3DVolumeTexture9(IDirect3DVo return CONTAINING_RECORD(iface, struct d3d9_texture, IDirect3DBaseTexture9_iface); }
-static void STDMETHODCALLTYPE srv_wined3d_object_destroyed(void *parent) -{ - struct d3d9_texture *texture = parent; - - texture->wined3d_srv = NULL; -} - -static const struct wined3d_parent_ops d3d9_srv_wined3d_parent_ops = -{ - srv_wined3d_object_destroyed, -}; - -/* wined3d critical section must be taken by the caller. */ -static struct wined3d_shader_resource_view *d3d9_texture_acquire_shader_resource_view(struct d3d9_texture *texture) -{ - struct wined3d_sub_resource_desc sr_desc; - struct wined3d_view_desc desc; - HRESULT hr; - - if (texture->wined3d_srv) - return texture->wined3d_srv; - - wined3d_texture_get_sub_resource_desc(texture->wined3d_texture, 0, &sr_desc); - desc.format_id = sr_desc.format; - desc.flags = 0; - desc.u.texture.level_idx = 0; - desc.u.texture.level_count = wined3d_texture_get_level_count(texture->wined3d_texture); - desc.u.texture.layer_idx = 0; - desc.u.texture.layer_count = sr_desc.usage & WINED3DUSAGE_LEGACY_CUBEMAP ? 6 : 1; - if (FAILED(hr = wined3d_shader_resource_view_create(&desc, - wined3d_texture_get_resource(d3d9_texture_get_draw_texture(texture)), texture, - &d3d9_srv_wined3d_parent_ops, &texture->wined3d_srv))) - { - ERR("Failed to create shader resource view, hr %#lx.\n", hr); - return NULL; - } - - return texture->wined3d_srv; -} - /* wined3d critical section must be taken by the caller. */ void d3d9_texture_gen_auto_mipmap(struct d3d9_texture *texture) { if (!(texture->flags & D3D9_TEXTURE_MIPMAP_DIRTY)) return; - d3d9_texture_acquire_shader_resource_view(texture); if (texture->draw_texture) wined3d_device_update_texture(texture->parent_device->wined3d_device, texture->wined3d_texture, texture->draw_texture); - wined3d_device_context_generate_mipmaps(texture->parent_device->immediate_context, texture->wined3d_srv); + wined3d_device_context_generate_mipmaps(texture->parent_device->immediate_context, + wined3d_texture_acquire_identity_srv(d3d9_texture_get_draw_texture(texture))); texture->flags &= ~D3D9_TEXTURE_MIPMAP_DIRTY; }
From: Zebediah Figura zfigura@codeweavers.com
The idea is to reuse the existing code to handle SRVs, which simplifies the GL code and essentially allows the Vulkan code to work "for free" (which is to say, by writing this patch, rather than by adding support for flat textures to the Vulkan renderer.)
This is a large patch; it consists the following parts:
* Create identity SRVs for d3d 1-9 textures. Store those in state->shader_resource_view instead of in state->texture.
* (Re)use wined3d_context_gl_bind_shader_resources() instead of state_sampler() to bind them.
- Introduce code to that function to handle FFP textures.
- Bind the sRGB texture if necessary in wined3d_shader_resource_view_gl_bind.
* (Re)use context_gl_load_shader_resources() instead of context_preload_textures() to load them.
- Introduce code to that function to handle FFP textures.
- Load the sRGB texture if necessary.
- Port the SRV/RTV feedback loop check from context_preload_textures().
* Invalidate STATE_GRAPHICS_SHADER_RESOURCE_BINDING in places that now need to account for texture binding being guarded by that state instead of STATE_SAMPLER.
Transitioning the remaining users of STATE_SAMPLER to STATE_GRAPHICS_SHADER_RESOURCE_BINDING, and removing STATE_SAMPLER, is left for future patches. --- dlls/wined3d/arb_program_shader.c | 6 +- dlls/wined3d/context.c | 71 ---------------------- dlls/wined3d/context_gl.c | 85 +++++++++++++++++++++++++- dlls/wined3d/cs.c | 99 +++++++++++++++++-------------- dlls/wined3d/device.c | 13 ---- dlls/wined3d/glsl_shader.c | 9 +-- dlls/wined3d/shader.c | 11 +++- dlls/wined3d/state.c | 57 +----------------- dlls/wined3d/stateblock.c | 37 ++++++------ dlls/wined3d/texture.c | 8 +-- dlls/wined3d/view.c | 2 +- dlls/wined3d/wined3d_private.h | 11 ++-- 12 files changed, 177 insertions(+), 232 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 6169d0d0c02..3ae82383146 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -490,11 +490,7 @@ static void shader_arb_load_np2fixup_constants(const struct arb_ps_np2fixup_info while (active) { i = wined3d_bit_scan(&active); - if (!(tex = state->textures[i])) - { - ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n"); - continue; - } + tex = texture_from_resource(state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i]->resource);
idx = fixup->super.idx[i]; tex_dim = &np2fixup_constants[(idx >> 1) * 4]; diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index ce3c18be4f1..90a588415ea 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -333,74 +333,3 @@ void context_update_stream_info(struct wined3d_context *context, const struct wi context->use_immediate_mode_draw = TRUE; } } - -static bool is_resource_rtv_bound(const struct wined3d_state *state, - const struct wined3d_resource *resource) -{ - unsigned int i; - - if (!resource->rtv_bind_count_device) - return false; - - for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) - { - if (state->fb.render_targets[i] && state->fb.render_targets[i]->resource == resource) - return true; - } - - return false; -} - -/* Context activation is done by the caller. */ -static void context_preload_texture(struct wined3d_context *context, - const struct wined3d_state *state, enum wined3d_shader_type shader_type, unsigned int idx) -{ - struct wined3d_texture *texture; - unsigned int texture_idx = idx; - - if (shader_type == WINED3D_SHADER_TYPE_VERTEX) - texture_idx += WINED3D_VERTEX_SAMPLER_OFFSET; - - if (!(texture = state->textures[texture_idx])) - return; - - if (is_resource_rtv_bound(state, &texture->resource) - || (state->fb.depth_stencil && state->fb.depth_stencil->resource == &texture->resource)) - context->uses_fbo_attached_resources = 1; - - wined3d_texture_load(texture, context, state->sampler[shader_type][idx]->desc.srgb_decode); -} - -/* Context activation is done by the caller. */ -void context_preload_textures(struct wined3d_context *context, const struct wined3d_state *state) -{ - unsigned int i; - - if (use_vs(state)) - { - for (i = 0; i < WINED3D_MAX_VERTEX_SAMPLERS; ++i) - { - if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.resource_info[i].type) - context_preload_texture(context, state, WINED3D_SHADER_TYPE_VERTEX, i); - } - } - - if (use_ps(state)) - { - for (i = 0; i < WINED3D_MAX_FRAGMENT_SAMPLERS; ++i) - { - if (state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.resource_info[i].type) - context_preload_texture(context, state, WINED3D_SHADER_TYPE_PIXEL, i); - } - } - else - { - uint32_t ffu_map = context->fixed_function_usage_map; - - while (ffu_map) - { - i = wined3d_bit_scan(&ffu_map); - context_preload_texture(context, state, WINED3D_SHADER_TYPE_PIXEL, i); - } - } -} diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 0cfe26170eb..55546130d35 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -3808,6 +3808,7 @@ static void wined3d_context_gl_map_fixed_function_samplers(struct wined3d_contex { wined3d_context_gl_map_stage(context_gl, i, i); context_invalidate_state(&context_gl->c, STATE_SAMPLER(i)); + context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); context_invalidate_texture_stage(&context_gl->c, i); } } @@ -3823,6 +3824,7 @@ static void wined3d_context_gl_map_fixed_function_samplers(struct wined3d_contex { wined3d_context_gl_map_stage(context_gl, i, tex); context_invalidate_state(&context_gl->c, STATE_SAMPLER(i)); + context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); context_invalidate_texture_stage(&context_gl->c, i); }
@@ -3843,6 +3845,7 @@ static void wined3d_context_gl_map_psamplers(struct wined3d_context_gl *context_ { wined3d_context_gl_map_stage(context_gl, i, i); context_invalidate_state(&context_gl->c, STATE_SAMPLER(i)); + context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); if (i < d3d_info->ffp_fragment_caps.max_blend_stages) context_invalidate_texture_stage(&context_gl->c, i); } @@ -3905,6 +3908,7 @@ static void wined3d_context_gl_map_vsamplers(struct wined3d_context_gl *context_ { wined3d_context_gl_map_stage(context_gl, vsampler_idx, start); context_invalidate_state(&context_gl->c, STATE_SAMPLER(vsampler_idx)); + context_invalidate_state(&context_gl->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING); }
--start; @@ -3976,7 +3980,37 @@ static void wined3d_context_gl_bind_shader_resources(struct wined3d_context_gl * struct wined3d_sampler *sampler;
if (!(shader = state->shader[shader_type])) + { + if (shader_type == WINED3D_SHADER_TYPE_PIXEL) + { + uint32_t ffu_map = context_gl->c.fixed_function_usage_map; + + while (ffu_map) + { + i = wined3d_bit_scan(&ffu_map); + bind_idx = context_gl->tex_unit_map[i]; + + view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i]; + sampler = state->sampler[WINED3D_SHADER_TYPE_PIXEL][i]; + + if (view) + { + wined3d_shader_resource_view_gl_bind(wined3d_shader_resource_view_gl(view), + bind_idx, wined3d_sampler_gl(sampler), context_gl); + } + else + { + WARN("No resource view bound at index %u.\n", i); + wined3d_context_gl_active_texture(context_gl, gl_info, bind_idx); + wined3d_context_gl_bind_texture(context_gl, GL_NONE, 0); + if (gl_info->supported[ARB_SAMPLER_OBJECTS]) + GL_EXTCALL(glBindSampler(bind_idx, 0)); + } + } + } + return; + }
tex_unit_map = wined3d_context_gl_get_tex_unit_mapping(context_gl, &shader->reg_maps.shader_version, &base, &count); @@ -4067,12 +4101,32 @@ static void wined3d_context_gl_bind_unordered_access_views(struct wined3d_contex checkGLcall("Bind unordered access views"); }
+static bool is_resource_rtv_bound(const struct wined3d_state *state, const struct wined3d_resource *resource) +{ + unsigned int i; + + if (state->fb.depth_stencil && state->fb.depth_stencil->resource == resource) + return true; + + if (!resource->rtv_bind_count_device) + return false; + + for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i) + { + if (state->fb.render_targets[i] && state->fb.render_targets[i]->resource == resource) + return true; + } + + return false; +} + static void context_gl_load_shader_resources(struct wined3d_context_gl *context_gl, const struct wined3d_state *state, unsigned int shader_mask) { struct wined3d_shader_sampler_map_entry *entry; struct wined3d_shader_resource_view_gl *srv_gl; struct wined3d_shader_resource_view *view; + struct wined3d_sampler *sampler; struct wined3d_shader *shader; struct wined3d_buffer *buffer; unsigned int i, j; @@ -4083,7 +4137,26 @@ static void context_gl_load_shader_resources(struct wined3d_context_gl *context_ continue;
if (!(shader = state->shader[i])) + { + if (i == WINED3D_SHADER_TYPE_PIXEL) + { + uint32_t ffu_map = context_gl->c.fixed_function_usage_map; + + while (ffu_map) + { + i = wined3d_bit_scan(&ffu_map); + + view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i]; + sampler = state->sampler[WINED3D_SHADER_TYPE_PIXEL][i]; + + if (view) + wined3d_texture_load(texture_from_resource(view->resource), + &context_gl->c, sampler->desc.srgb_decode); + } + } + continue; + }
for (j = 0; j < WINED3D_MAX_CBS; ++j) { @@ -4104,6 +4177,9 @@ static void context_gl_load_shader_resources(struct wined3d_context_gl *context_ if (!(view = state->shader_resource_view[i][entry->resource_idx])) continue;
+ if (is_resource_rtv_bound(state, view->resource)) + context_gl->c.uses_fbo_attached_resources = 1; + if (view->resource->type == WINED3D_RTYPE_BUFFER) { buffer = buffer_from_resource(view->resource); @@ -4116,7 +4192,13 @@ static void context_gl_load_shader_resources(struct wined3d_context_gl *context_ } else { - wined3d_texture_load(texture_from_resource(view->resource), &context_gl->c, FALSE); + BOOL srgb = TRUE; + + if (entry->sampler_idx != WINED3D_SAMPLER_DEFAULT + && (sampler = state->sampler[i][entry->sampler_idx])) + srgb = sampler->desc.srgb_decode; + + wined3d_texture_load(texture_from_resource(view->resource), &context_gl->c, srgb); } } } @@ -4213,7 +4295,6 @@ static BOOL context_apply_draw_state(struct wined3d_context *context, * result in changes to the current FBO, due to using e.g. FBO blits for * updating a resource location. */ wined3d_context_gl_update_tex_unit_map(context_gl, state); - context_preload_textures(context, state); context_gl_load_shader_resources(context_gl, state, ~(1u << WINED3D_SHADER_TYPE_COMPUTE)); context_gl_load_unordered_access_resources(context_gl, state->shader[WINED3D_SHADER_TYPE_PIXEL], state->unordered_access_view[WINED3D_PIPELINE_GRAPHICS]); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 84c025ff46c..7c6e465844c 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -270,8 +270,9 @@ struct wined3d_cs_set_constant_buffers struct wined3d_cs_set_texture { enum wined3d_cs_op opcode; - UINT stage; - struct wined3d_texture *texture; + enum wined3d_shader_type shader_type; + unsigned int bind_index; + struct wined3d_shader_resource_view *view; };
struct wined3d_cs_set_color_key @@ -1036,11 +1037,6 @@ static void reference_graphics_pipeline_resources(struct wined3d_device_context if (state->stream_output[i].buffer) wined3d_device_context_reference_resource(context, &state->stream_output[i].buffer->resource); } - for (i = 0; i < ARRAY_SIZE(state->textures); ++i) - { - if (state->textures[i]) - wined3d_device_context_reference_resource(context, &state->textures[i]->resource); - } for (i = 0; i < d3d_info->limits.max_rt_count; ++i) { if (state->fb.render_targets[i]) @@ -1454,8 +1450,8 @@ void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_cont wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); }
-static bool texture_binding_might_invalidate_ps(struct wined3d_texture *texture, - struct wined3d_texture *prev, const struct wined3d_d3d_info *d3d_info) +static bool texture_binding_might_invalidate_ps(struct wined3d_shader_resource_view *view, + struct wined3d_shader_resource_view *prev, const struct wined3d_d3d_info *d3d_info) { unsigned int old_usage, new_usage, old_caps, new_caps; const struct wined3d_format *old_format, *new_format; @@ -1464,16 +1460,16 @@ static bool texture_binding_might_invalidate_ps(struct wined3d_texture *texture, return true;
/* 1.x pixel shaders need to be recompiled based on the resource type. */ - old_usage = prev->resource.usage; - new_usage = texture->resource.usage; - if (texture->resource.type != prev->resource.type + old_usage = prev->resource->usage; + new_usage = view->resource->usage; + if (view->resource->type != prev->resource->type || ((old_usage & WINED3DUSAGE_LEGACY_CUBEMAP) != (new_usage & WINED3DUSAGE_LEGACY_CUBEMAP))) return true;
- old_format = prev->resource.format; - new_format = texture->resource.format; - old_caps = prev->resource.format_caps; - new_caps = texture->resource.format_caps; + old_format = prev->resource->format; + new_format = view->resource->format; + old_caps = prev->resource->format_caps; + new_caps = view->resource->format_caps; if ((old_caps & WINED3D_FORMAT_CAP_SHADOW) != (new_caps & WINED3D_FORMAT_CAP_SHADOW)) return true;
@@ -1490,47 +1486,61 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) { const struct wined3d_d3d_info *d3d_info = &cs->c.device->adapter->d3d_info; const struct wined3d_cs_set_texture *op = data; - struct wined3d_texture *prev; + struct wined3d_shader_resource_view *prev; BOOL old_use_color_key = FALSE, new_use_color_key = FALSE;
- prev = cs->state.textures[op->stage]; - cs->state.textures[op->stage] = op->texture; + prev = cs->state.shader_resource_view[op->shader_type][op->bind_index]; + cs->state.shader_resource_view[op->shader_type][op->bind_index] = op->view;
- if (op->texture) + if (op->view) { - ++op->texture->resource.bind_count; + struct wined3d_texture *texture = texture_from_resource(op->view->resource);
- if (texture_binding_might_invalidate_ps(op->texture, prev, d3d_info)) - device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); + ++op->view->resource->bind_count;
- if (!prev && op->stage < d3d_info->ffp_fragment_caps.max_blend_stages) + if (op->shader_type == WINED3D_SHADER_TYPE_PIXEL) { - /* The source arguments for color and alpha ops have different - * meanings when a NULL texture is bound, so the COLOR_OP and - * ALPHA_OP have to be dirtified. */ - device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); - device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); - } + if (texture_binding_might_invalidate_ps(op->view, prev, d3d_info)) + device_invalidate_state(cs->c.device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
- if (!op->stage && op->texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) - new_use_color_key = TRUE; + if (!prev && op->bind_index < d3d_info->ffp_fragment_caps.max_blend_stages) + { + /* The source arguments for color and alpha ops have different + * meanings when a NULL texture is bound, so the COLOR_OP and + * ALPHA_OP have to be dirtified. */ + device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->bind_index, WINED3D_TSS_COLOR_OP)); + device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->bind_index, WINED3D_TSS_ALPHA_OP)); + } + + if (!op->bind_index && texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) + new_use_color_key = TRUE; + } }
if (prev) { - --prev->resource.bind_count; + struct wined3d_texture *prev_texture = texture_from_resource(prev->resource); + + --prev->resource->bind_count;
- if (!op->texture && op->stage < d3d_info->ffp_fragment_caps.max_blend_stages) + if (op->shader_type == WINED3D_SHADER_TYPE_PIXEL) { - device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); - device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); - } + if (!op->view && op->bind_index < d3d_info->ffp_fragment_caps.max_blend_stages) + { + device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->bind_index, WINED3D_TSS_COLOR_OP)); + device_invalidate_state(cs->c.device, STATE_TEXTURESTAGE(op->bind_index, WINED3D_TSS_ALPHA_OP)); + }
- if (!op->stage && prev->async.color_key_flags & WINED3D_CKEY_SRC_BLT) - old_use_color_key = TRUE; + if (!op->bind_index && prev_texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT) + old_use_color_key = TRUE; + } }
- device_invalidate_state(cs->c.device, STATE_SAMPLER(op->stage)); + if (op->shader_type == WINED3D_SHADER_TYPE_VERTEX) + device_invalidate_state(cs->c.device, STATE_SAMPLER(WINED3D_VERTEX_SAMPLER_OFFSET + op->bind_index)); + else + device_invalidate_state(cs->c.device, STATE_SAMPLER(op->bind_index)); + device_invalidate_state(cs->c.device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
if (new_use_color_key != old_use_color_key) device_invalidate_state(cs->c.device, STATE_RENDER(WINED3D_RS_COLORKEYENABLE)); @@ -1539,15 +1549,16 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) device_invalidate_state(cs->c.device, STATE_COLOR_KEY); }
-void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, unsigned int stage, - struct wined3d_texture *texture) +void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, + enum wined3d_shader_type shader_type, unsigned int bind_index, struct wined3d_shader_resource_view *view) { struct wined3d_cs_set_texture *op;
op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); op->opcode = WINED3D_CS_OP_SET_TEXTURE; - op->stage = stage; - op->texture = texture; + op->shader_type = shader_type; + op->bind_index = bind_index; + op->view = view;
wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 21848f9cea4..201b76eab28 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5108,19 +5108,6 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso
switch (type) { - case WINED3D_RTYPE_TEXTURE_1D: - case WINED3D_RTYPE_TEXTURE_2D: - case WINED3D_RTYPE_TEXTURE_3D: - for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) - { - if (&state->textures[i]->resource == resource) - { - ERR("Texture resource %p is still in use, stage %u.\n", resource, i); - state->textures[i] = NULL; - } - } - break; - case WINED3D_RTYPE_BUFFER: for (i = 0; i < WINED3D_MAX_STREAMS; ++i) { diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index ed6f2bb8e83..a9775d94cf1 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1299,15 +1299,10 @@ static void shader_glsl_load_np2fixup_constants(const struct glsl_ps_program *ps
for (i = 0; fixup; fixup >>= 1, ++i) { - const struct wined3d_texture *tex = state->textures[i]; unsigned char idx = ps->np2_fixup_info->idx[i]; + const struct wined3d_texture *tex;
- if (!tex) - { - ERR("Nonexistent texture is flagged for NP2 texcoord fixup.\n"); - continue; - } - + tex = texture_from_resource(state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i]->resource); np2fixup_constants[idx].sx = tex->pow2_matrix[0]; np2fixup_constants[idx].sy = tex->pow2_matrix[5]; } diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index b58546db875..5d4eb1543b2 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2777,6 +2777,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context) { const struct wined3d_d3d_info *d3d_info = context->d3d_info; + struct wined3d_shader_resource_view *view; struct wined3d_texture *texture; unsigned int i;
@@ -2858,8 +2859,9 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 /* Treat unbound textures as 2D. The dummy texture will provide * the proper sample value. The tex_types bitmap defaults to * 2D because of the memset. */ - if (!(texture = state->textures[i])) + if (!(view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i])) continue; + texture = texture_from_resource(view->resource);
switch (wined3d_texture_gl(texture)->target) { @@ -2900,8 +2902,9 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 break; }
- if ((texture = state->textures[i])) + if ((view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i])) { + texture = texture_from_resource(view->resource); /* Star Wars: The Old Republic uses mismatched samplers for rendering water. */ if (texture->resource.type == WINED3D_RTYPE_TEXTURE_2D && resource_type == WINED3D_SHADER_RESOURCE_TEXTURE_3D @@ -2930,11 +2933,13 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 if (!shader->reg_maps.resource_info[i].type) continue;
- if (!(texture = state->textures[i])) + if (!(view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][i])) { args->color_fixup[i] = COLOR_FIXUP_IDENTITY; continue; } + texture = texture_from_resource(view->resource); + if (can_use_texture_swizzle(d3d_info, texture->resource.format)) args->color_fixup[i] = COLOR_FIXUP_IDENTITY; else diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 87fa7c454fe..5333382ab81 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3453,59 +3453,8 @@ static void sampler_texmatrix(struct wined3d_context *context, const struct wine } }
-/* Enabling and disabling texture dimensions is done by texture stage state / - * pixel shader setup, this function only has to bind textures and set the per - * texture states. */ static void sampler(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - struct wined3d_context_gl *context_gl = wined3d_context_gl(context); - unsigned int sampler_idx = state_id - STATE_SAMPLER(0); - unsigned int mapped_stage = context_gl->tex_unit_map[sampler_idx]; - const struct wined3d_gl_info *gl_info = context_gl->gl_info; - - TRACE("Sampler %u.\n", sampler_idx); - - if (mapped_stage == WINED3D_UNMAPPED_STAGE) - { - TRACE("No sampler mapped to stage %u. Returning.\n", sampler_idx); - return; - } - - if (mapped_stage >= gl_info->limits.graphics_samplers) - return; - wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage); - - if (state->textures[sampler_idx]) - { - struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(state->textures[sampler_idx]); - enum wined3d_shader_type shader_type = WINED3D_SHADER_TYPE_PIXEL; - unsigned int bind_idx = sampler_idx; - struct wined3d_sampler *sampler; - - if (sampler_idx >= WINED3D_VERTEX_SAMPLER_OFFSET) - { - bind_idx -= WINED3D_VERTEX_SAMPLER_OFFSET; - shader_type = WINED3D_SHADER_TYPE_VERTEX; - } - - sampler = state->sampler[shader_type][bind_idx]; - - wined3d_texture_gl_bind(texture_gl, context_gl, sampler->desc.srgb_decode); - wined3d_sampler_gl_bind(wined3d_sampler_gl(sampler), mapped_stage, texture_gl, context_gl); - - /* Trigger shader constant reloading (for NP2 texcoord fixup) */ - if (!(texture_gl->t.flags & WINED3D_TEXTURE_POW2_MAT_IDENT)) - context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP; - } - else - { - wined3d_context_gl_bind_texture(context_gl, GL_NONE, 0); - if (gl_info->supported[ARB_SAMPLER_OBJECTS]) - { - GL_EXTCALL(glBindSampler(mapped_stage, 0)); - checkGLcall("glBindSampler"); - } - } }
void apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -3519,11 +3468,7 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta /* Former draw without a pixel shader, some samplers may be * disabled because of WINED3D_TSS_COLOR_OP = WINED3DTOP_DISABLE * make sure to enable them. */ - for (i = 0; i < WINED3D_MAX_FRAGMENT_SAMPLERS; ++i) - { - if (!isStateDirty(context, STATE_SAMPLER(i))) - sampler(context, state, STATE_SAMPLER(i)); - } + context->update_shader_resource_bindings = 1; context->last_was_pshader = TRUE; } else diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 6361de4909b..a17e166bad6 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -431,7 +431,6 @@ void state_unbind_resources(struct wined3d_state *state) struct wined3d_blend_state *blend_state; struct wined3d_rendertarget_view *rtv; struct wined3d_sampler *sampler; - struct wined3d_texture *texture; struct wined3d_buffer *buffer; struct wined3d_shader *shader; unsigned int i, j; @@ -442,15 +441,6 @@ void state_unbind_resources(struct wined3d_state *state) wined3d_vertex_declaration_decref(decl); }
- for (i = 0; i < WINED3D_MAX_COMBINED_SAMPLERS; ++i) - { - if ((texture = state->textures[i])) - { - state->textures[i] = NULL; - wined3d_texture_decref(texture); - } - } - for (i = 0; i < WINED3D_MAX_STREAM_OUTPUT_BUFFERS; ++i) { if ((buffer = state->stream_output[i].buffer)) @@ -2530,28 +2520,37 @@ static void wined3d_device_set_texture_stage_state(struct wined3d_device *device static void wined3d_device_set_texture(struct wined3d_device *device, unsigned int stage, struct wined3d_texture *texture) { + enum wined3d_shader_type shader_type = WINED3D_SHADER_TYPE_PIXEL; + struct wined3d_shader_resource_view *srv = NULL, *prev; struct wined3d_state *state = device->cs->c.state; - struct wined3d_texture *prev;
TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
- prev = state->textures[stage]; + if (stage >= WINED3D_VERTEX_SAMPLER_OFFSET) + { + shader_type = WINED3D_SHADER_TYPE_VERTEX; + stage -= WINED3D_VERTEX_SAMPLER_OFFSET; + } + + if (texture && !(srv = wined3d_texture_acquire_identity_srv(texture))) + return; + + prev = state->shader_resource_view[shader_type][stage]; TRACE("Previous texture %p.\n", prev);
- if (texture == prev) + if (srv == prev) { TRACE("App is setting the same texture again, nothing to do.\n"); return; }
- TRACE("Setting new texture to %p.\n", texture); - state->textures[stage] = texture; + state->shader_resource_view[shader_type][stage] = srv;
- if (texture) - wined3d_texture_incref(texture); - wined3d_device_context_emit_set_texture(&device->cs->c, stage, texture); + if (srv) + wined3d_shader_resource_view_incref(srv); + wined3d_device_context_emit_set_texture(&device->cs->c, shader_type, stage, srv); if (prev) - wined3d_texture_decref(prev); + wined3d_shader_resource_view_decref(prev);
return; } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 09eea050d9c..8a7f9455bb0 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -3515,7 +3515,6 @@ static void texture_resource_unload(struct wined3d_resource *resource) { struct wined3d_texture *texture = texture_from_resource(resource); struct wined3d_device *device = resource->device; - const struct wined3d_state *state = &device->cs->state; unsigned int location = resource->map_binding; struct wined3d_context *context; unsigned int sub_count, i; @@ -3561,11 +3560,8 @@ static void texture_resource_unload(struct wined3d_resource *resource)
wined3d_texture_force_reload(texture);
- for (i = 0; i < ARRAY_SIZE(state->textures); ++i) - { - if (state->textures[i] == texture) - device_invalidate_state(device, STATE_SAMPLER(i)); - } + if (texture->resource.bind_count && (texture->resource.bind_flags & WINED3D_BIND_SHADER_RESOURCE)) + device_invalidate_state(device, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
wined3d_texture_set_dirty(texture);
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 5174075cdd2..967c758b1ed 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -1288,7 +1288,7 @@ void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl }
texture_gl = wined3d_texture_gl(wined3d_texture_from_resource(view_gl->v.resource)); - wined3d_texture_gl_bind(texture_gl, context_gl, FALSE); + wined3d_texture_gl_bind(texture_gl, context_gl, sampler_gl->s.desc.srgb_decode); wined3d_sampler_gl_bind(sampler_gl, unit, texture_gl, context_gl);
/* Trigger shader constant reloading (for NP2 texcoord fixup) */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 429c6632716..f0992082c90 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1976,7 +1976,6 @@ struct wined3d_context
void wined3d_context_cleanup(struct wined3d_context *context) DECLSPEC_HIDDEN; void wined3d_context_init(struct wined3d_context *context, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; -void context_preload_textures(struct wined3d_context *context, const struct wined3d_state *state) DECLSPEC_HIDDEN; void context_update_stream_info(struct wined3d_context *context, const struct wined3d_state *state) DECLSPEC_HIDDEN;
HRESULT wined3d_context_no3d_init(struct wined3d_context *context_no3d, @@ -2884,7 +2883,6 @@ struct wined3d_state struct wined3d_shader_resource_view *shader_resource_view[WINED3D_SHADER_TYPE_COUNT][MAX_SHADER_RESOURCE_VIEWS]; struct wined3d_unordered_access_view *unordered_access_view[WINED3D_PIPELINE_COUNT][MAX_UNORDERED_ACCESS_VIEWS];
- struct wined3d_texture *textures[WINED3D_MAX_COMBINED_SAMPLERS]; uint32_t texture_states[WINED3D_MAX_FFP_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1];
struct wined3d_matrix transforms[WINED3D_HIGHEST_TRANSFORM_STATE + 1]; @@ -3730,8 +3728,9 @@ void wined3d_device_context_emit_set_stream_outputs(struct wined3d_device_contex const struct wined3d_stream_output outputs[WINED3D_MAX_STREAM_OUTPUT_BUFFERS]) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context *context, unsigned int start_idx, unsigned int count, const struct wined3d_stream_state *streams) DECLSPEC_HIDDEN; -void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, unsigned int stage, - struct wined3d_texture *texture) DECLSPEC_HIDDEN; +void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, + enum wined3d_shader_type shader_type, unsigned int bind_index, + struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_texture_state(struct wined3d_device_context *context, unsigned int stage, enum wined3d_texture_stage_state state, unsigned int value) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_transform(struct wined3d_device_context *context, @@ -3941,8 +3940,10 @@ void wined3d_shader_resource_view_destroy(struct wined3d_shader_resource_view *v
static inline struct wined3d_texture *wined3d_state_get_ffp_texture(const struct wined3d_state *state, unsigned int idx) { + struct wined3d_shader_resource_view *view = state->shader_resource_view[WINED3D_SHADER_TYPE_PIXEL][idx]; + assert(idx <= WINED3D_MAX_FFP_TEXTURES); - return state->textures[idx]; + return view ? texture_from_resource(view->resource) : NULL; }
struct wined3d_unordered_access_view
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=140591
Your paranoid android.
=== debian11 (build log) ===
error: patch failed: dlls/wined3d/wined3d_private.h:3935 error: patch failed: dlls/wined3d/wined3d_private.h:1976 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/wined3d/wined3d_private.h:3935 error: patch failed: dlls/wined3d/wined3d_private.h:1976 Task: Patch failed to apply
On Thu Nov 30 20:27:35 2023 +0000, Zebediah Figura wrote:
changed this line in [version 4 of the diff](/wine/wine/-/merge_requests/4436/diffs?diff_id=87081&start_sha=8d0286341039b2a0d5db36e9857671ae4017bc29#9a64884c14a2525b4b8c4cbe467933ed46644357_997_997)
Fixed in the latest revision.
This merge request was approved by Zebediah Figura.
This merge request was approved by Jan Sikorski.