diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index fccad043dbc..e4102e3db26 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -523,6 +523,8 @@ get_imageview_for_binding(struct zink_context *ctx, gl_shader_stage stage, enum /* if this is a non-seamless cube sampler, return the cube array view */ return (ctx->di.emulate_nonseamless[stage] & ctx->di.cubes[stage] & BITFIELD_BIT(idx)) ? sampler_view->cube_array : + sampler_view->shadow && stage == MESA_SHADER_FRAGMENT && ctx->gfx_stages[MESA_SHADER_FRAGMENT] && + (ctx->di.shadow.mask & ctx->gfx_stages[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask & BITFIELD_BIT(idx)) ? sampler_view->shadow : sampler_view->image_view; } case ZINK_DESCRIPTOR_TYPE_IMAGE: { @@ -672,6 +674,13 @@ update_descriptor_state_sampler(struct zink_context *ctx, gl_shader_stage shader return res; } +void +zink_update_shadow_samplerviews(struct zink_context *ctx, unsigned mask) +{ + u_foreach_bit(slot, mask) + update_descriptor_state_sampler(ctx, MESA_SHADER_FRAGMENT, slot, ctx->di.descriptor_res[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW][MESA_SHADER_FRAGMENT][slot]); +} + ALWAYS_INLINE static struct zink_resource * update_descriptor_state_image(struct zink_context *ctx, gl_shader_stage shader, unsigned slot, struct zink_resource *res) { @@ -1002,6 +1011,7 @@ zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres, ivci = create_ivci(screen, res, &templ, state->target); ivci.subresourceRange.levelCount = state->u.tex.last_level - state->u.tex.first_level + 1; ivci.subresourceRange.aspectMask = sampler_aspect_from_format(state->format); + bool shadow_needs_shader_swizzle = false; /* samplers for stencil aspects of packed formats need to always use stencil swizzle */ if (ivci.subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { if (sampler_view->base.swizzle_r == PIPE_SWIZZLE_0 && @@ -1027,7 +1037,7 @@ zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres, for (unsigned i = 0; i < 4; i++) { /* these require shader rewrites to correctly emulate */ if (swizzle[i] == VK_COMPONENT_SWIZZLE_ONE || swizzle[i] == VK_COMPONENT_SWIZZLE_ZERO) - sampler_view->shadow_needs_shader_swizzle = true; + shadow_needs_shader_swizzle = true; } /* this is the data that will be used in shader rewrites */ sampler_view->swizzle.s[0] = clamp_zs_swizzle(sampler_view->base.swizzle_r); @@ -1090,6 +1100,15 @@ zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres, if (!screen->info.have_EXT_non_seamless_cube_map && viewtype_is_cube(&sampler_view->image_view->ivci)) { ivci.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; sampler_view->cube_array = (struct zink_surface*)zink_get_surface(ctx, pres, &templ, &ivci); + } else if (shadow_needs_shader_swizzle) { + /* there is only one component, and real swizzling can't be done here, + * so ensure the shader gets the sampled data + */ + ivci.components.r = VK_COMPONENT_SWIZZLE_R; + ivci.components.g = VK_COMPONENT_SWIZZLE_R; + ivci.components.b = VK_COMPONENT_SWIZZLE_R; + ivci.components.a = VK_COMPONENT_SWIZZLE_R; + sampler_view->shadow = (struct zink_surface*)zink_get_surface(ctx, pres, &templ, &ivci); } err = !sampler_view->image_view; } else { @@ -1137,6 +1156,7 @@ zink_sampler_view_destroy(struct pipe_context *pctx, else { zink_surface_reference(zink_screen(pctx->screen), &view->image_view, NULL); zink_surface_reference(zink_screen(pctx->screen), &view->cube_array, NULL); + zink_surface_reference(zink_screen(pctx->screen), &view->shadow, NULL); } pipe_resource_reference(&pview->texture, NULL); FREE_CL(view); @@ -1951,7 +1971,7 @@ zink_set_sampler_views(struct pipe_context *pctx, update = true; zink_batch_resource_usage_set(&ctx->batch, res, false, false); res->obj->unordered_write = false; - if (b->shadow_needs_shader_swizzle) { + if (b->shadow) { assert(start_slot + i < 32); //bitfield size ctx->di.shadow.mask |= BITFIELD_BIT(start_slot + i); /* this is already gonna be slow, so don't bother trying to micro-optimize */ diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 3fd64a87e4c..e20980a335f 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -211,6 +211,9 @@ zink_component_mapping(enum pipe_swizzle swizzle) } } +void +zink_update_shadow_samplerviews(struct zink_context *ctx, unsigned mask); + enum pipe_swizzle zink_clamp_void_swizzle(const struct util_format_description *desc, enum pipe_swizzle swizzle); diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 8a688db10f1..fad06eb1d29 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -1475,6 +1475,7 @@ zink_bind_fs_state(struct pipe_context *pctx, struct zink_context *ctx = zink_context(pctx); if (!cso && !ctx->gfx_stages[MESA_SHADER_FRAGMENT]) return; + unsigned shadow_mask = ctx->gfx_stages[MESA_SHADER_FRAGMENT] ? ctx->gfx_stages[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask : 0; bind_gfx_stage(ctx, MESA_SHADER_FRAGMENT, cso); ctx->fbfetch_outputs = 0; if (cso) { @@ -1492,6 +1493,8 @@ zink_bind_fs_state(struct pipe_context *pctx, ctx->gfx_pipeline_state.rast_attachment_order = nir->info.fs.uses_fbfetch_output; } zink_set_fs_shadow_needs_shader_swizzle_key(ctx, false); + if (shadow_mask != ctx->gfx_stages[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask) + zink_update_shadow_samplerviews(ctx, shadow_mask | ctx->gfx_stages[MESA_SHADER_FRAGMENT]->fs.legacy_shadow_mask); } zink_update_fbfetch(ctx); } diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 616983b23f4..f51bc1d54d4 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1470,7 +1470,7 @@ struct zink_sampler_view { struct zink_buffer_view *buffer_view; }; struct zink_surface *cube_array; - bool shadow_needs_shader_swizzle; + struct zink_surface *shadow; struct zink_fs_shadow_swizzle swizzle; };