summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/state_tracker/st_pbo.c83
-rw-r--r--src/mesa/state_tracker/st_pbo.h3
2 files changed, 79 insertions, 7 deletions
diff --git a/src/mesa/state_tracker/st_pbo.c b/src/mesa/state_tracker/st_pbo.c
index 794a1fcbf6c..7c43b9fc61b 100644
--- a/src/mesa/state_tracker/st_pbo.c
+++ b/src/mesa/state_tracker/st_pbo.c
@@ -359,12 +359,13 @@ st_pbo_create_gs(struct st_context *st)
return ureg_create_shader_and_destroy(ureg, st->pipe);
}
-void *
-st_pbo_create_upload_fs(struct st_context *st)
+static void *
+create_fs(struct st_context *st, bool download, enum pipe_texture_target target)
{
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct ureg_program *ureg;
+ bool have_layer;
struct ureg_dst out;
struct ureg_src sampler;
struct ureg_src pos;
@@ -372,11 +373,29 @@ st_pbo_create_upload_fs(struct st_context *st)
struct ureg_src const0;
struct ureg_dst temp0;
+ have_layer =
+ st->pbo.layers &&
+ (!download || target == PIPE_TEXTURE_1D_ARRAY
+ || target == PIPE_TEXTURE_2D_ARRAY
+ || target == PIPE_TEXTURE_3D
+ || target == PIPE_TEXTURE_CUBE
+ || target == PIPE_TEXTURE_CUBE_ARRAY);
+
ureg = ureg_create(PIPE_SHADER_FRAGMENT);
if (!ureg)
return NULL;
- out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ if (!download) {
+ out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ } else {
+ struct ureg_src image;
+
+ /* writeonly images do not require an explicitly given format. */
+ image = ureg_DECL_image(ureg, 0, TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE,
+ true, false);
+ out = ureg_dst(image);
+ }
+
sampler = ureg_DECL_sampler(ureg, 0);
if (screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) {
pos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0);
@@ -384,7 +403,7 @@ st_pbo_create_upload_fs(struct st_context *st)
pos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
TGSI_INTERPOLATE_LINEAR);
}
- if (st->pbo.layers) {
+ if (have_layer) {
layer = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_LAYER, 0,
TGSI_INTERPOLATE_CONSTANT);
}
@@ -414,7 +433,7 @@ st_pbo_create_upload_fs(struct st_context *st)
ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X));
- if (st->pbo.layers) {
+ if (have_layer) {
/* temp0.x = const0.w * layer + temp0.x */
ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X),
ureg_scalar(const0, TGSI_SWIZZLE_W),
@@ -425,8 +444,41 @@ st_pbo_create_upload_fs(struct st_context *st)
/* temp0.w = 0 */
ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_W), ureg_imm1u(ureg, 0));
- /* out = txf(sampler, temp0.x) */
- ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler);
+ if (download) {
+ struct ureg_dst temp1;
+ struct ureg_src op[2];
+
+ temp1 = ureg_DECL_temporary(ureg);
+
+ /* temp1.xy = pos.xy */
+ ureg_F2I(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_XY), pos);
+
+ /* temp1.zw = 0 */
+ ureg_MOV(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_ZW), ureg_imm1u(ureg, 0));
+
+ if (have_layer) {
+ /* temp1.y/z = layer */
+ ureg_MOV(ureg, ureg_writemask(temp1,
+ target == PIPE_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_Y
+ : TGSI_WRITEMASK_Z),
+ ureg_scalar(layer, TGSI_SWIZZLE_X));
+ }
+
+ /* temp1 = txf(sampler, temp1) */
+ ureg_TXF(ureg, temp1, util_pipe_tex_to_tgsi_tex(target, 1),
+ ureg_src(temp1), sampler);
+
+ /* store(out, temp0, temp1) */
+ op[0] = ureg_src(temp0);
+ op[1] = ureg_src(temp1);
+ ureg_memory_insn(ureg, TGSI_OPCODE_STORE, &out, 1, op, 2, 0,
+ TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE);
+
+ ureg_release_temporary(ureg, temp1);
+ } else {
+ /* out = txf(sampler, temp0.x) */
+ ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler);
+ }
ureg_release_temporary(ureg, temp0);
@@ -435,6 +487,23 @@ st_pbo_create_upload_fs(struct st_context *st)
return ureg_create_shader_and_destroy(ureg, pipe);
}
+void *
+st_pbo_create_upload_fs(struct st_context *st)
+{
+ return create_fs(st, false, 0);
+}
+
+void *
+st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target)
+{
+ assert(target < PIPE_MAX_TEXTURE_TYPES);
+
+ if (!st->pbo.download_fs[target])
+ st->pbo.download_fs[target] = create_fs(st, true, target);
+
+ return st->pbo.download_fs[target];
+}
+
void
st_init_pbo_helpers(struct st_context *st)
{
diff --git a/src/mesa/state_tracker/st_pbo.h b/src/mesa/state_tracker/st_pbo.h
index fb1b7378545..c17ac1702e3 100644
--- a/src/mesa/state_tracker/st_pbo.h
+++ b/src/mesa/state_tracker/st_pbo.h
@@ -82,6 +82,9 @@ st_pbo_create_gs(struct st_context *st);
void *
st_pbo_create_upload_fs(struct st_context *st);
+void *
+st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target);
+
extern void
st_init_pbo_helpers(struct st_context *st);