diff options
author | Marek Olšák <[email protected]> | 2019-06-20 18:24:19 -0400 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2019-07-03 15:51:12 -0400 |
commit | 6686d8a130bb195d0e926d52f0e1e0f9243569be (patch) | |
tree | e4de820d9022a7609dad8fde06ae22845c55a34e /src/gallium/auxiliary/util/u_simple_shaders.c | |
parent | 13a5e9d68528236676ff7975fcf61ca26ae3baa0 (diff) |
gallium/u_blitter: implement copying from ZS to color and vice versa
This is for drivers that can't map depth and stencil and need to blit
them to a color texture for CPU access.
This also useful for drivers using separate depth and stencil.
Tested-by: Dieter Nützel <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/util/u_simple_shaders.c')
-rw-r--r-- | src/gallium/auxiliary/util/u_simple_shaders.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index c111eaf1db5..2fdd60b0bb3 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -895,3 +895,164 @@ util_make_geometry_passthrough_shader(struct pipe_context *pipe, return ureg_create_shader_and_destroy(ureg, pipe); } +/** + * Blit from color to ZS or from ZS to color in a manner that is equivalent + * to memcpy. + * + * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24). + * + * Depth and stencil samplers are used to load depth and stencil, + * and they are packed and the result is written to a color output. + * OR + * A color sampler is used to load a color value, which is unpacked and + * written to depth and stencil shader outputs. + */ +void * +util_make_fs_pack_color_zs(struct pipe_context *pipe, + enum tgsi_texture_type tex_target, + enum pipe_format zs_format, + bool dst_is_color) +{ + struct ureg_program *ureg; + struct ureg_src depth_sampler, stencil_sampler, color_sampler, coord; + struct ureg_dst out, depth, depth_x, stencil, out_depth, out_stencil, color; + + assert(zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || /* color is R32G32_UINT */ + zs_format == PIPE_FORMAT_Z24X8_UNORM || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_X8Z24_UNORM); /* color is R32_UINT */ + + bool has_stencil = zs_format != PIPE_FORMAT_Z24X8_UNORM && + zs_format != PIPE_FORMAT_X8Z24_UNORM; + bool is_z24 = zs_format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT; + bool z24_is_high = zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || + zs_format == PIPE_FORMAT_X8Z24_UNORM; + + ureg = ureg_create(PIPE_SHADER_FRAGMENT); + if (!ureg) + return NULL; + + coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + + if (dst_is_color) { + /* Load depth. */ + depth_sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT); + + depth = ureg_DECL_temporary(ureg); + depth_x = ureg_writemask(depth, TGSI_WRITEMASK_X); + ureg_load_tex(ureg, depth_x, coord, depth_sampler, tex_target, true, true); + + /* Pack to Z24. */ + if (is_z24) { + double imm = 0xffffff; + struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2); + struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg), + TGSI_WRITEMASK_XY); + + ureg_F2D(ureg, tmp_xy, ureg_src(depth)); + ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64); + ureg_D2U(ureg, depth_x, ureg_src(tmp_xy)); + + if (z24_is_high) + ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8)); + else + ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff)); + } + + if (has_stencil) { + /* Load stencil. */ + stencil_sampler = ureg_DECL_sampler(ureg, 1); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT); + + stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target, + true, true); + + /* Pack stencil into depth. */ + if (is_z24) { + if (!z24_is_high) + ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24)); + + ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil)); + } + } + + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + if (is_z24) { + ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth)); + } else { + /* Z32_S8X24 */ + ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Y), + ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X)); + ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_XY), ureg_src(depth)); + } + } else { + color_sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT); + + color = ureg_DECL_temporary(ureg); + ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true); + + depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + + if (is_z24) { + double imm = 1.0 / 0xffffff; + struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2); + struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg), + TGSI_WRITEMASK_XY); + + ureg_UBFE(ureg, depth, ureg_src(color), + ureg_imm1u(ureg, z24_is_high ? 8 : 0), + ureg_imm1u(ureg, 24)); + ureg_U2D(ureg, tmp_xy, ureg_src(depth)); + ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64); + ureg_D2F(ureg, depth, ureg_src(tmp_xy)); + } else { + /* depth = color.x; (Z32_S8X24) */ + ureg_MOV(ureg, depth, ureg_src(color)); + } + + out_depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + ureg_MOV(ureg, ureg_writemask(out_depth, TGSI_WRITEMASK_Z), + ureg_scalar(ureg_src(depth), TGSI_SWIZZLE_X)); + + if (has_stencil) { + if (is_z24) { + ureg_UBFE(ureg, stencil, ureg_src(color), + ureg_imm1u(ureg, z24_is_high ? 0 : 24), + ureg_imm1u(ureg, 8)); + } else { + /* stencil = color.y[0:7]; (Z32_S8X24) */ + ureg_UBFE(ureg, stencil, + ureg_scalar(ureg_src(color), TGSI_SWIZZLE_Y), + ureg_imm1u(ureg, 0), + ureg_imm1u(ureg, 8)); + } + + out_stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0); + ureg_MOV(ureg, ureg_writemask(out_stencil, TGSI_WRITEMASK_Y), + ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X)); + } + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} |