Module: Mesa Branch: main Commit: 64e0ca15d6986768af18cfa2b553576196d54260 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=64e0ca15d6986768af18cfa2b553576196d54260
Author: Mike Blumenkrantz <[email protected]> Date: Thu Oct 28 15:17:11 2021 -0400 zink: add 1DShadow sampler handling for drivers (radv) that don't support it some drivers won't create zs textures in any shape but 2D. this can be handled instead by using 2D textures and then performing shader rewrites to convert shadow samplers for 1D and 1DArray types to 2D/array Reviewed-by: Dave Airlie <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13583> --- src/gallium/drivers/zink/zink_blit.c | 10 ++++- src/gallium/drivers/zink/zink_compiler.c | 67 ++++++++++++++++++++++++++++++++ src/gallium/drivers/zink/zink_context.c | 15 +++++-- src/gallium/drivers/zink/zink_resource.c | 6 ++- src/gallium/drivers/zink/zink_resource.h | 1 + src/gallium/drivers/zink/zink_screen.c | 7 ++++ src/gallium/drivers/zink/zink_screen.h | 1 + src/gallium/drivers/zink/zink_surface.c | 4 +- 8 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/zink/zink_blit.c b/src/gallium/drivers/zink/zink_blit.c index 8055111afe0..6734b562604 100644 --- a/src/gallium/drivers/zink/zink_blit.c +++ b/src/gallium/drivers/zink/zink_blit.c @@ -176,7 +176,10 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info) region.srcOffsets[1].x = info->src.box.x + info->src.box.width; region.srcOffsets[1].y = info->src.box.y + info->src.box.height; - switch (src->base.b.target) { + enum pipe_texture_target src_target = src->base.b.target; + if (src->need_2D_zs) + src_target = src_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY; + switch (src_target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: case PIPE_TEXTURE_2D_ARRAY: @@ -211,7 +214,10 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info) assert(region.dstOffsets[0].x != region.dstOffsets[1].x); assert(region.dstOffsets[0].y != region.dstOffsets[1].y); - switch (dst->base.b.target) { + enum pipe_texture_target dst_target = dst->base.b.target; + if (dst->need_2D_zs) + dst_target = dst_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY; + switch (dst_target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: case PIPE_TEXTURE_2D_ARRAY: diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 9de3604928a..ec34ddac2d4 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -1637,6 +1637,70 @@ get_shader_base_prim_type(struct nir_shader *nir) return PIPE_PRIM_MAX; } +static bool +convert_1d_shadow_tex(nir_builder *b, nir_instr *instr, void *data) +{ + if (instr->type != nir_instr_type_tex) + return false; + nir_tex_instr *tex = nir_instr_as_tex(instr); + if (tex->sampler_dim != GLSL_SAMPLER_DIM_1D || !tex->is_shadow) + return false; + tex->sampler_dim = GLSL_SAMPLER_DIM_2D; + b->cursor = nir_before_instr(instr); + tex->coord_components++; + unsigned srcs[] = { + nir_tex_src_coord, + nir_tex_src_offset, + nir_tex_src_ddx, + nir_tex_src_ddy, + }; + for (unsigned i = 0; i < ARRAY_SIZE(srcs); i++) { + unsigned c = nir_tex_instr_src_index(tex, srcs[i]); + if (c == -1) + continue; + if (tex->src[c].src.ssa->num_components == tex->coord_components) + continue; + nir_ssa_def *def; + nir_ssa_def *zero = nir_imm_zero(b, 1, tex->src[c].src.ssa->bit_size); + if (tex->src[c].src.ssa->num_components == 1) + def = nir_vec2(b, tex->src[c].src.ssa, zero); + else + def = nir_vec3(b, nir_channel(b, tex->src[c].src.ssa, 0), zero, nir_channel(b, tex->src[c].src.ssa, 1)); + nir_instr_rewrite_src_ssa(instr, &tex->src[c].src, def); + } + b->cursor = nir_after_instr(instr); + unsigned needed_components = nir_tex_instr_dest_size(tex); + unsigned num_components = tex->dest.ssa.num_components; + if (needed_components > num_components) { + tex->dest.ssa.num_components = needed_components; + assert(num_components < 3); + /* take either xz or just x since this is promoted to 2D from 1D */ + uint32_t mask = num_components == 2 ? (1|4) : 1; + nir_ssa_def *dst = nir_channels(b, &tex->dest.ssa, mask); + nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, dst, dst->parent_instr); + } + return true; +} + +static bool +lower_1d_shadow(nir_shader *shader) +{ + bool found = false; + nir_foreach_variable_with_modes(var, shader, nir_var_uniform | nir_var_image) { + const struct glsl_type *type = glsl_without_array(var->type); + unsigned length = glsl_get_length(var->type); + if (!glsl_type_is_sampler(type) || !glsl_sampler_type_is_shadow(type) || glsl_get_sampler_dim(type) != GLSL_SAMPLER_DIM_1D) + continue; + const struct glsl_type *sampler = glsl_sampler_type(GLSL_SAMPLER_DIM_2D, true, glsl_sampler_type_is_array(type), glsl_get_sampler_result_type(type)); + var->type = type != var->type ? glsl_array_type(sampler, length, glsl_get_explicit_stride(var->type)) : sampler; + + found = true; + } + if (found) + nir_shader_instructions_pass(shader, convert_1d_shadow_tex, nir_metadata_dominance, NULL); + return found; +} + struct zink_shader * zink_shader_create(struct zink_screen *screen, struct nir_shader *nir, const struct pipe_stream_output_info *so_info) @@ -1673,6 +1737,9 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir, NIR_PASS_V(nir, nir_lower_regs_to_ssa); NIR_PASS_V(nir, lower_baseinstance); + if (screen->need_2D_zs) + NIR_PASS_V(nir, lower_1d_shadow); + { nir_lower_subgroups_options subgroup_options = {0}; subgroup_options.lower_to_scalar = true; diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 48d701a139e..75b376369c9 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3398,7 +3398,10 @@ zink_copy_image_buffer(struct zink_context *ctx, struct zink_resource *dst, stru region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.mipLevel = buf2img ? dst_level : src_level; - switch (img->base.b.target) { + enum pipe_texture_target img_target = img->base.b.target; + if (img->need_2D_zs) + img_target = img_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY; + switch (img_target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: case PIPE_TEXTURE_2D_ARRAY: @@ -3494,7 +3497,10 @@ zink_resource_copy_region(struct pipe_context *pctx, region.srcSubresource.aspectMask = src->aspect; region.srcSubresource.mipLevel = src_level; - switch (src->base.b.target) { + enum pipe_texture_target src_target = src->base.b.target; + if (src->need_2D_zs) + src_target = src_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY; + switch (src_target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: case PIPE_TEXTURE_2D_ARRAY: @@ -3525,7 +3531,10 @@ zink_resource_copy_region(struct pipe_context *pctx, region.dstSubresource.aspectMask = dst->aspect; region.dstSubresource.mipLevel = dst_level; - switch (dst->base.b.target) { + enum pipe_texture_target dst_target = dst->base.b.target; + if (dst->need_2D_zs) + dst_target = dst_target == PIPE_TEXTURE_1D ? PIPE_TEXTURE_2D : PIPE_TEXTURE_2D_ARRAY; + switch (dst_target) { case PIPE_TEXTURE_CUBE: case PIPE_TEXTURE_CUBE_ARRAY: case PIPE_TEXTURE_2D_ARRAY: diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 384d2c7dd42..d8254a19f7d 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -334,10 +334,12 @@ create_ici(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe ici->usage = 0; ici->queueFamilyIndexCount = 0; + bool need_2D_zs = false; switch (templ->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_1D_ARRAY: - ici->imageType = VK_IMAGE_TYPE_1D; + need_2D_zs = screen->need_2D_zs && util_format_is_depth_or_stencil(templ->format); + ici->imageType = need_2D_zs ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D; break; case PIPE_TEXTURE_CUBE: @@ -787,6 +789,8 @@ resource_create(struct pipe_screen *pscreen, } } else { res->format = zink_get_format(screen, templ->format); + res->need_2D_zs = screen->need_2D_zs && util_format_is_depth_or_stencil(templ->format) && + (templ->target == PIPE_TEXTURE_1D || templ->target == PIPE_TEXTURE_1D_ARRAY); res->dmabuf_acquire = whandle && whandle->type == WINSYS_HANDLE_TYPE_FD; res->layout = res->dmabuf_acquire ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; res->optimal_tiling = optimal_tiling; diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 8602c1b69cf..7dd07c72b5b 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -110,6 +110,7 @@ struct zink_resource { VkImageLayout layout; VkImageAspectFlags aspect; bool optimal_tiling; + bool need_2D_zs; uint8_t fb_binds; //not counted in all_binds }; }; diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 393ec41d477..061ed27d890 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1571,6 +1571,13 @@ populate_format_props(struct zink_screen *screen) } else VKSCR(GetPhysicalDeviceFormatProperties)(screen->pdev, format, &screen->format_props[i]); } + VkImageFormatProperties image_props; + VkResult ret = VKSCR(GetPhysicalDeviceImageFormatProperties)(screen->pdev, VK_FORMAT_D32_SFLOAT, + VK_IMAGE_TYPE_1D, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, &image_props); + screen->need_2D_zs = ret != VK_SUCCESS; } bool diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index a1b7811935d..e16cdae8dcf 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -126,6 +126,7 @@ struct zink_screen { bool have_X8_D24_UNORM_PACK32; bool have_D24_UNORM_S8_UINT; bool have_triangle_fans; + bool need_2D_zs; uint32_t gfx_queue; uint32_t max_queues; diff --git a/src/gallium/drivers/zink/zink_surface.c b/src/gallium/drivers/zink/zink_surface.c index e7af9963529..dc1ddf05acd 100644 --- a/src/gallium/drivers/zink/zink_surface.c +++ b/src/gallium/drivers/zink/zink_surface.c @@ -45,11 +45,11 @@ create_ivci(struct zink_screen *screen, switch (target) { case PIPE_TEXTURE_1D: - ivci.viewType = VK_IMAGE_VIEW_TYPE_1D; + ivci.viewType = res->need_2D_zs ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D; break; case PIPE_TEXTURE_1D_ARRAY: - ivci.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY; + ivci.viewType = res->need_2D_zs ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_1D_ARRAY; break; case PIPE_TEXTURE_2D:
