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 50ed82ad358..143f8b485b0 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -1290,7 +1290,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