softpipe: add image support to softpipe (v3)
This adds support for ARB_shader_image_load_store to softpipe. v2: add RESQ support (Ilia) v3: constify, cleanup internals, add some comments (Brian). Reviewed-by: Brian Paul <brianp@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
0d1f679ded
commit
eb9ad9faa3
|
@ -497,8 +497,10 @@ tgsi_exec_get_shader_param(enum pipe_shader_cap param)
|
|||
case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
|
||||
case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
|
||||
case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
|
||||
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
|
||||
return 0;
|
||||
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
|
||||
return PIPE_MAX_SHADER_IMAGES;
|
||||
|
||||
case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
|
||||
return 32;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ C_SOURCES := \
|
|||
sp_flush.h \
|
||||
sp_fs_exec.c \
|
||||
sp_fs.h \
|
||||
sp_image.c \
|
||||
sp_limits.h \
|
||||
sp_prim_vbuf.c \
|
||||
sp_prim_vbuf.h \
|
||||
|
@ -31,6 +32,7 @@ C_SOURCES := \
|
|||
sp_state_blend.c \
|
||||
sp_state_clip.c \
|
||||
sp_state_derived.c \
|
||||
sp_state_image.c \
|
||||
sp_state.h \
|
||||
sp_state_rasterizer.c \
|
||||
sp_state_sampler.c \
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
#include "sp_query.h"
|
||||
#include "sp_screen.h"
|
||||
#include "sp_tex_sample.h"
|
||||
|
||||
#include "sp_image.h"
|
||||
|
||||
static void
|
||||
softpipe_destroy( struct pipe_context *pipe )
|
||||
|
@ -199,6 +199,10 @@ softpipe_create_context(struct pipe_screen *screen,
|
|||
softpipe->tgsi.sampler[i] = sp_create_tgsi_sampler();
|
||||
}
|
||||
|
||||
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
|
||||
softpipe->tgsi.image[i] = sp_create_tgsi_image();
|
||||
}
|
||||
|
||||
softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
|
||||
softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
|
||||
|
||||
|
@ -216,6 +220,7 @@ softpipe_create_context(struct pipe_screen *screen,
|
|||
softpipe_init_streamout_funcs(&softpipe->pipe);
|
||||
softpipe_init_texture_funcs( &softpipe->pipe );
|
||||
softpipe_init_vertex_funcs(&softpipe->pipe);
|
||||
softpipe_init_image_funcs(&softpipe->pipe);
|
||||
|
||||
softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
|
||||
|
||||
|
@ -223,7 +228,8 @@ softpipe_create_context(struct pipe_screen *screen,
|
|||
|
||||
softpipe->pipe.clear = softpipe_clear;
|
||||
softpipe->pipe.flush = softpipe_flush_wrapped;
|
||||
|
||||
softpipe->pipe.texture_barrier = softpipe_texture_barrier;
|
||||
softpipe->pipe.memory_barrier = softpipe_memory_barrier;
|
||||
softpipe->pipe.render_condition = softpipe_render_condition;
|
||||
|
||||
/*
|
||||
|
@ -272,6 +278,16 @@ softpipe_create_context(struct pipe_screen *screen,
|
|||
(struct tgsi_sampler *)
|
||||
softpipe->tgsi.sampler[PIPE_SHADER_GEOMETRY]);
|
||||
|
||||
draw_image(softpipe->draw,
|
||||
PIPE_SHADER_VERTEX,
|
||||
(struct tgsi_image *)
|
||||
softpipe->tgsi.image[PIPE_SHADER_VERTEX]);
|
||||
|
||||
draw_image(softpipe->draw,
|
||||
PIPE_SHADER_GEOMETRY,
|
||||
(struct tgsi_image *)
|
||||
softpipe->tgsi.image[PIPE_SHADER_GEOMETRY]);
|
||||
|
||||
if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
|
||||
softpipe->no_rast = TRUE;
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ struct softpipe_context {
|
|||
struct pipe_scissor_state scissors[PIPE_MAX_VIEWPORTS];
|
||||
struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||
|
||||
struct pipe_image_view images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
|
||||
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
|
||||
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
|
||||
struct pipe_index_buffer index_buffer;
|
||||
|
@ -172,6 +173,7 @@ struct softpipe_context {
|
|||
/** TGSI exec things */
|
||||
struct {
|
||||
struct sp_tgsi_sampler *sampler[PIPE_SHADER_TYPES];
|
||||
struct sp_tgsi_image *image[PIPE_SHADER_TYPES];
|
||||
} tgsi;
|
||||
|
||||
struct tgsi_exec_machine *fs_machine;
|
||||
|
|
|
@ -168,3 +168,29 @@ softpipe_flush_resource(struct pipe_context *pipe,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void softpipe_texture_barrier(struct pipe_context *pipe)
|
||||
{
|
||||
struct softpipe_context *softpipe = softpipe_context(pipe);
|
||||
uint i, sh;
|
||||
|
||||
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
|
||||
for (i = 0; i < softpipe->num_sampler_views[sh]; i++) {
|
||||
sp_flush_tex_tile_cache(softpipe->tex_cache[sh][i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++)
|
||||
if (softpipe->cbuf_cache[i])
|
||||
sp_flush_tile_cache(softpipe->cbuf_cache[i]);
|
||||
|
||||
if (softpipe->zsbuf_cache)
|
||||
sp_flush_tile_cache(softpipe->zsbuf_cache);
|
||||
|
||||
softpipe->dirty_render_cache = FALSE;
|
||||
}
|
||||
|
||||
void softpipe_memory_barrier(struct pipe_context *pipe, unsigned flags)
|
||||
{
|
||||
softpipe_texture_barrier(pipe);
|
||||
}
|
||||
|
|
|
@ -55,4 +55,6 @@ softpipe_flush_resource(struct pipe_context *pipe,
|
|||
boolean cpu_access,
|
||||
boolean do_not_block);
|
||||
|
||||
void softpipe_texture_barrier(struct pipe_context *pipe);
|
||||
void softpipe_memory_barrier(struct pipe_context *pipe, unsigned flags);
|
||||
#endif
|
||||
|
|
|
@ -62,14 +62,15 @@ sp_exec_fragment_shader(const struct sp_fragment_shader_variant *var)
|
|||
static void
|
||||
exec_prepare( const struct sp_fragment_shader_variant *var,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct tgsi_sampler *sampler )
|
||||
struct tgsi_sampler *sampler,
|
||||
struct tgsi_image *image )
|
||||
{
|
||||
/*
|
||||
* Bind tokens/shader to the interpreter's machine state.
|
||||
*/
|
||||
tgsi_exec_machine_bind_shader(machine,
|
||||
var->tokens,
|
||||
sampler, NULL);
|
||||
sampler, image);
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,6 +128,7 @@ exec_run( const struct sp_fragment_shader_variant *var,
|
|||
/* convert 0 to 1.0 and 1 to -1.0 */
|
||||
machine->Face = (float) (quad->input.facing * -2 + 1);
|
||||
|
||||
machine->NonHelperMask = quad->inout.mask;
|
||||
quad->inout.mask &= tgsi_exec_machine_run( machine );
|
||||
if (quad->inout.mask == 0)
|
||||
return FALSE;
|
||||
|
|
|
@ -0,0 +1,762 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sp_context.h"
|
||||
#include "sp_image.h"
|
||||
#include "sp_texture.h"
|
||||
|
||||
#include "util/u_format.h"
|
||||
|
||||
/*
|
||||
* Get the offset into the base image
|
||||
* first element for a buffer or layer/level for texture.
|
||||
*/
|
||||
static uint32_t
|
||||
get_image_offset(const struct softpipe_resource *spr,
|
||||
const struct pipe_image_view *iview,
|
||||
enum pipe_format format, unsigned r_coord)
|
||||
{
|
||||
int base_layer = 0;
|
||||
|
||||
if (spr->base.target == PIPE_BUFFER)
|
||||
return iview->u.buf.first_element * util_format_get_blocksize(format);
|
||||
|
||||
if (spr->base.target == PIPE_TEXTURE_1D_ARRAY ||
|
||||
spr->base.target == PIPE_TEXTURE_2D_ARRAY ||
|
||||
spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
|
||||
spr->base.target == PIPE_TEXTURE_CUBE ||
|
||||
spr->base.target == PIPE_TEXTURE_3D)
|
||||
base_layer = r_coord + iview->u.tex.first_layer;
|
||||
return softpipe_get_tex_image_offset(spr, iview->u.tex.level, base_layer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does this texture instruction have a layer or depth parameter.
|
||||
*/
|
||||
static inline bool
|
||||
has_layer_or_depth(unsigned tgsi_tex_instr)
|
||||
{
|
||||
return (tgsi_tex_instr == TGSI_TEXTURE_3D ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_CUBE ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_CUBE_ARRAY ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY_MSAA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this texture instruction a single non-array coordinate.
|
||||
*/
|
||||
static inline bool
|
||||
has_1coord(unsigned tgsi_tex_instr)
|
||||
{
|
||||
return (tgsi_tex_instr == TGSI_TEXTURE_BUFFER ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_1D ||
|
||||
tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* check the bounds vs w/h/d
|
||||
*/
|
||||
static inline bool
|
||||
bounds_check(int width, int height, int depth,
|
||||
int s, int t, int r)
|
||||
{
|
||||
if (s < 0 || s >= width)
|
||||
return false;
|
||||
if (t < 0 || t >= height)
|
||||
return false;
|
||||
if (r < 0 || r >= depth)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the texture target compatible with the image resource
|
||||
* pipe target.
|
||||
*/
|
||||
static inline bool
|
||||
has_compat_target(unsigned pipe_target, unsigned tgsi_target)
|
||||
{
|
||||
switch (pipe_target) {
|
||||
case PIPE_TEXTURE_1D:
|
||||
if (tgsi_target == TGSI_TEXTURE_1D)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_2D:
|
||||
if (tgsi_target == TGSI_TEXTURE_2D)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_RECT:
|
||||
if (tgsi_target == TGSI_TEXTURE_RECT)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_3D:
|
||||
if (tgsi_target == TGSI_TEXTURE_3D ||
|
||||
tgsi_target == TGSI_TEXTURE_2D)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
if (tgsi_target == TGSI_TEXTURE_CUBE ||
|
||||
tgsi_target == TGSI_TEXTURE_2D)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_1D_ARRAY:
|
||||
if (tgsi_target == TGSI_TEXTURE_1D ||
|
||||
tgsi_target == TGSI_TEXTURE_1D_ARRAY)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_2D_ARRAY:
|
||||
if (tgsi_target == TGSI_TEXTURE_2D ||
|
||||
tgsi_target == TGSI_TEXTURE_2D_ARRAY)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_TEXTURE_CUBE_ARRAY:
|
||||
if (tgsi_target == TGSI_TEXTURE_CUBE ||
|
||||
tgsi_target == TGSI_TEXTURE_CUBE_ARRAY ||
|
||||
tgsi_target == TGSI_TEXTURE_2D)
|
||||
return true;
|
||||
break;
|
||||
case PIPE_BUFFER:
|
||||
return (tgsi_target == TGSI_TEXTURE_BUFFER);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
get_dimensions(const struct pipe_image_view *iview,
|
||||
const struct softpipe_resource *spr,
|
||||
unsigned tgsi_tex_instr,
|
||||
enum pipe_format pformat,
|
||||
unsigned *width,
|
||||
unsigned *height,
|
||||
unsigned *depth)
|
||||
{
|
||||
if (tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
|
||||
*width = iview->u.buf.last_element - iview->u.buf.first_element + 1;
|
||||
*height = 1;
|
||||
*depth = 1;
|
||||
/*
|
||||
* Bounds check the buffer size from the view
|
||||
* and the buffer size from the underlying buffer.
|
||||
*/
|
||||
if (util_format_get_stride(pformat, *width) >
|
||||
util_format_get_stride(spr->base.format, spr->base.width0))
|
||||
return false;
|
||||
} else {
|
||||
unsigned level;
|
||||
|
||||
level = spr->base.target == PIPE_BUFFER ? 0 : iview->u.tex.level;
|
||||
*width = u_minify(spr->base.width0, level);
|
||||
*height = u_minify(spr->base.height0, level);
|
||||
|
||||
if (spr->base.target == TGSI_TEXTURE_3D)
|
||||
*depth = u_minify(spr->base.depth0, level);
|
||||
else
|
||||
*depth = spr->base.array_size;
|
||||
|
||||
/* Make sure the resource and view have compatiable formats */
|
||||
if (util_format_get_blocksize(pformat) >
|
||||
util_format_get_blocksize(spr->base.format))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_coords(const struct tgsi_image_params *params,
|
||||
unsigned index,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
int *s_coord, int *t_coord, int *r_coord)
|
||||
{
|
||||
*s_coord = s[index];
|
||||
*t_coord = has_1coord(params->tgsi_tex_instr) ? 0 : t[index];
|
||||
*r_coord = has_layer_or_depth(params->tgsi_tex_instr) ?
|
||||
(params->tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ? t[index] : r[index]) : 0;
|
||||
}
|
||||
/*
|
||||
* Implement the image LOAD operation.
|
||||
*/
|
||||
static void
|
||||
sp_tgsi_load(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
|
||||
{
|
||||
struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
|
||||
struct pipe_image_view *iview;
|
||||
struct softpipe_resource *spr;
|
||||
unsigned width, height, depth;
|
||||
unsigned stride;
|
||||
int c, j;
|
||||
char *data_ptr;
|
||||
unsigned offset = 0;
|
||||
|
||||
if (params->unit > PIPE_MAX_SHADER_IMAGES)
|
||||
goto fail_write_all_zero;
|
||||
iview = &sp_img->sp_iview[params->unit];
|
||||
spr = (struct softpipe_resource *)iview->resource;
|
||||
if (!spr)
|
||||
goto fail_write_all_zero;
|
||||
|
||||
if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
|
||||
goto fail_write_all_zero;
|
||||
|
||||
if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
|
||||
params->format, &width, &height, &depth))
|
||||
return;
|
||||
|
||||
stride = util_format_get_stride(params->format, width);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
int s_coord, t_coord, r_coord;
|
||||
bool fill_zero = false;
|
||||
|
||||
if (!(params->execmask & (1 << j)))
|
||||
fill_zero = true;
|
||||
|
||||
fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
|
||||
if (!bounds_check(width, height, depth,
|
||||
s_coord, t_coord, r_coord))
|
||||
fill_zero = true;
|
||||
|
||||
if (fill_zero) {
|
||||
int nc = util_format_get_nr_components(params->format);
|
||||
int ival = util_format_is_pure_integer(params->format);
|
||||
for (c = 0; c < 4; c++) {
|
||||
rgba[c][j] = 0;
|
||||
if (c == 3 && nc < 4) {
|
||||
if (ival)
|
||||
((int32_t *)rgba[c])[j] = 1;
|
||||
else
|
||||
rgba[c][j] = 1.0;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
offset = get_image_offset(spr, iview, params->format, r_coord);
|
||||
data_ptr = (char *)spr->data + offset;
|
||||
|
||||
if (util_format_is_pure_sint(params->format)) {
|
||||
int32_t sdata[4];
|
||||
|
||||
util_format_read_4i(params->format,
|
||||
sdata, 0,
|
||||
data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
for (c = 0; c < 4; c++)
|
||||
((int32_t *)rgba[c])[j] = sdata[c];
|
||||
} else if (util_format_is_pure_uint(params->format)) {
|
||||
uint32_t sdata[4];
|
||||
util_format_read_4ui(params->format,
|
||||
sdata, 0,
|
||||
data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
for (c = 0; c < 4; c++)
|
||||
((uint32_t *)rgba[c])[j] = sdata[c];
|
||||
} else {
|
||||
float sdata[4];
|
||||
util_format_read_4f(params->format,
|
||||
sdata, 0,
|
||||
data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
for (c = 0; c < 4; c++)
|
||||
rgba[c][j] = sdata[c];
|
||||
}
|
||||
}
|
||||
return;
|
||||
fail_write_all_zero:
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
for (c = 0; c < 4; c++)
|
||||
rgba[c][j] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the image STORE operation.
|
||||
*/
|
||||
static void
|
||||
sp_tgsi_store(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
|
||||
{
|
||||
struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
|
||||
struct pipe_image_view *iview;
|
||||
struct softpipe_resource *spr;
|
||||
unsigned width, height, depth;
|
||||
unsigned stride;
|
||||
char *data_ptr;
|
||||
int j, c;
|
||||
unsigned offset = 0;
|
||||
unsigned pformat = params->format;
|
||||
|
||||
if (params->unit > PIPE_MAX_SHADER_IMAGES)
|
||||
return;
|
||||
iview = &sp_img->sp_iview[params->unit];
|
||||
spr = (struct softpipe_resource *)iview->resource;
|
||||
if (!spr)
|
||||
return;
|
||||
if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
|
||||
return;
|
||||
|
||||
if (params->format == PIPE_FORMAT_NONE)
|
||||
pformat = spr->base.format;
|
||||
|
||||
if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
|
||||
pformat, &width, &height, &depth))
|
||||
return;
|
||||
|
||||
stride = util_format_get_stride(pformat, width);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
int s_coord, t_coord, r_coord;
|
||||
|
||||
if (!(params->execmask & (1 << j)))
|
||||
continue;
|
||||
|
||||
fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
|
||||
if (!bounds_check(width, height, depth,
|
||||
s_coord, t_coord, r_coord))
|
||||
continue;
|
||||
|
||||
offset = get_image_offset(spr, iview, pformat, r_coord);
|
||||
data_ptr = (char *)spr->data + offset;
|
||||
|
||||
if (util_format_is_pure_sint(pformat)) {
|
||||
int32_t sdata[4];
|
||||
for (c = 0; c < 4; c++)
|
||||
sdata[c] = ((int32_t *)rgba[c])[j];
|
||||
util_format_write_4i(pformat, sdata, 0, data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
} else if (util_format_is_pure_uint(pformat)) {
|
||||
uint32_t sdata[4];
|
||||
for (c = 0; c < 4; c++)
|
||||
sdata[c] = ((uint32_t *)rgba[c])[j];
|
||||
util_format_write_4ui(pformat, sdata, 0, data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
} else {
|
||||
float sdata[4];
|
||||
for (c = 0; c < 4; c++)
|
||||
sdata[c] = rgba[c][j];
|
||||
util_format_write_4f(pformat, sdata, 0, data_ptr, stride,
|
||||
s_coord, t_coord, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement atomic operations on unsigned integers.
|
||||
*/
|
||||
static void
|
||||
handle_op_uint(const struct pipe_image_view *iview,
|
||||
const struct tgsi_image_params *params,
|
||||
bool just_read,
|
||||
char *data_ptr,
|
||||
uint qi,
|
||||
unsigned stride,
|
||||
unsigned opcode,
|
||||
int s,
|
||||
int t,
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
|
||||
float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
|
||||
{
|
||||
uint c;
|
||||
int nc = util_format_get_nr_components(params->format);
|
||||
unsigned sdata[4];
|
||||
|
||||
util_format_read_4ui(params->format,
|
||||
sdata, 0,
|
||||
data_ptr, stride,
|
||||
s, t, 1, 1);
|
||||
|
||||
if (just_read) {
|
||||
for (c = 0; c < nc; c++) {
|
||||
((uint32_t *)rgba[c])[qi] = sdata[c];
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (opcode) {
|
||||
case TGSI_OPCODE_ATOMUADD:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] += ((uint32_t *)rgba[c])[qi];
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMXCHG:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] = ((uint32_t *)rgba[c])[qi];
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMCAS:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned dst_x = sdata[c];
|
||||
unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
|
||||
unsigned src_x = ((uint32_t *)rgba2[c])[qi];
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMAND:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] &= ((uint32_t *)rgba[c])[qi];
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMOR:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] |= ((uint32_t *)rgba[c])[qi];
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMXOR:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned temp = sdata[c];
|
||||
sdata[c] ^= ((uint32_t *)rgba[c])[qi];
|
||||
((uint32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMUMIN:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned dst_x = sdata[c];
|
||||
unsigned src_x = ((uint32_t *)rgba[c])[qi];
|
||||
sdata[c] = MIN2(dst_x, src_x);
|
||||
((uint32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMUMAX:
|
||||
for (c = 0; c < nc; c++) {
|
||||
unsigned dst_x = sdata[c];
|
||||
unsigned src_x = ((uint32_t *)rgba[c])[qi];
|
||||
sdata[c] = MAX2(dst_x, src_x);
|
||||
((uint32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMIMIN:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((uint32_t *)rgba[c])[qi];
|
||||
sdata[c] = MIN2(dst_x, src_x);
|
||||
((uint32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMIMAX:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((uint32_t *)rgba[c])[qi];
|
||||
sdata[c] = MAX2(dst_x, src_x);
|
||||
((uint32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(!"Unexpected TGSI opcode in sp_tgsi_op");
|
||||
break;
|
||||
}
|
||||
util_format_write_4ui(params->format, sdata, 0, data_ptr, stride,
|
||||
s, t, 1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement atomic operations on signed integers.
|
||||
*/
|
||||
static void
|
||||
handle_op_int(const struct pipe_image_view *iview,
|
||||
const struct tgsi_image_params *params,
|
||||
bool just_read,
|
||||
char *data_ptr,
|
||||
uint qi,
|
||||
unsigned stride,
|
||||
unsigned opcode,
|
||||
int s,
|
||||
int t,
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
|
||||
float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
|
||||
{
|
||||
uint c;
|
||||
int nc = util_format_get_nr_components(params->format);
|
||||
int sdata[4];
|
||||
util_format_read_4i(params->format,
|
||||
sdata, 0,
|
||||
data_ptr, stride,
|
||||
s, t, 1, 1);
|
||||
|
||||
if (just_read) {
|
||||
for (c = 0; c < nc; c++) {
|
||||
((int32_t *)rgba[c])[qi] = sdata[c];
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (opcode) {
|
||||
case TGSI_OPCODE_ATOMUADD:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int temp = sdata[c];
|
||||
sdata[c] += ((int32_t *)rgba[c])[qi];
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMXCHG:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int temp = sdata[c];
|
||||
sdata[c] = ((int32_t *)rgba[c])[qi];
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMCAS:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int cmp_x = ((int32_t *)rgba[c])[qi];
|
||||
int src_x = ((int32_t *)rgba2[c])[qi];
|
||||
int temp = sdata[c];
|
||||
sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMAND:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int temp = sdata[c];
|
||||
sdata[c] &= ((int32_t *)rgba[c])[qi];
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMOR:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int temp = sdata[c];
|
||||
sdata[c] |= ((int32_t *)rgba[c])[qi];
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMXOR:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int temp = sdata[c];
|
||||
sdata[c] ^= ((int32_t *)rgba[c])[qi];
|
||||
((int32_t *)rgba[c])[qi] = temp;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMUMIN:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((int32_t *)rgba[c])[qi];
|
||||
sdata[c] = MIN2(dst_x, src_x);
|
||||
((int32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMUMAX:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((int32_t *)rgba[c])[qi];
|
||||
sdata[c] = MAX2(dst_x, src_x);
|
||||
((int32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMIMIN:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((int32_t *)rgba[c])[qi];
|
||||
sdata[c] = MIN2(dst_x, src_x);
|
||||
((int32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_ATOMIMAX:
|
||||
for (c = 0; c < nc; c++) {
|
||||
int dst_x = sdata[c];
|
||||
int src_x = ((int32_t *)rgba[c])[qi];
|
||||
sdata[c] = MAX2(dst_x, src_x);
|
||||
((int32_t *)rgba[c])[qi] = dst_x;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(!"Unexpected TGSI opcode in sp_tgsi_op");
|
||||
break;
|
||||
}
|
||||
util_format_write_4i(params->format, sdata, 0, data_ptr, stride,
|
||||
s, t, 1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement atomic image operations.
|
||||
*/
|
||||
static void
|
||||
sp_tgsi_op(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
unsigned opcode,
|
||||
const int s[TGSI_QUAD_SIZE],
|
||||
const int t[TGSI_QUAD_SIZE],
|
||||
const int r[TGSI_QUAD_SIZE],
|
||||
const int sample[TGSI_QUAD_SIZE],
|
||||
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
|
||||
float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
|
||||
{
|
||||
struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
|
||||
struct pipe_image_view *iview;
|
||||
struct softpipe_resource *spr;
|
||||
unsigned width, height, depth;
|
||||
unsigned stride;
|
||||
int j, c;
|
||||
unsigned offset;
|
||||
char *data_ptr;
|
||||
|
||||
if (params->unit > PIPE_MAX_SHADER_IMAGES)
|
||||
return;
|
||||
iview = &sp_img->sp_iview[params->unit];
|
||||
spr = (struct softpipe_resource *)iview->resource;
|
||||
if (!spr)
|
||||
goto fail_write_all_zero;
|
||||
if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
|
||||
goto fail_write_all_zero;
|
||||
|
||||
if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
|
||||
params->format, &width, &height, &depth))
|
||||
goto fail_write_all_zero;
|
||||
|
||||
stride = util_format_get_stride(spr->base.format, width);
|
||||
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
int s_coord, t_coord, r_coord;
|
||||
bool just_read = false;
|
||||
|
||||
fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
|
||||
if (!bounds_check(width, height, depth,
|
||||
s_coord, t_coord, r_coord)) {
|
||||
int nc = util_format_get_nr_components(params->format);
|
||||
int ival = util_format_is_pure_integer(params->format);
|
||||
int c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
rgba[c][j] = 0;
|
||||
if (c == 3 && nc < 4) {
|
||||
if (ival)
|
||||
((int32_t *)rgba[c])[j] = 1;
|
||||
else
|
||||
rgba[c][j] = 1.0;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* just readback the value for atomic if execmask isn't set */
|
||||
if (!(params->execmask & (1 << j))) {
|
||||
just_read = true;
|
||||
}
|
||||
|
||||
offset = get_image_offset(spr, iview, params->format, r_coord);
|
||||
data_ptr = (char *)spr->data + offset;
|
||||
|
||||
/* we should see atomic operations on r32 formats */
|
||||
if (util_format_is_pure_uint(params->format))
|
||||
handle_op_uint(iview, params, just_read, data_ptr, j, stride,
|
||||
opcode, s_coord, t_coord, rgba, rgba2);
|
||||
else if (util_format_is_pure_sint(params->format))
|
||||
handle_op_int(iview, params, just_read, data_ptr, j, stride,
|
||||
opcode, s_coord, t_coord, rgba, rgba2);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
return;
|
||||
fail_write_all_zero:
|
||||
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
|
||||
for (c = 0; c < 4; c++)
|
||||
rgba[c][j] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
sp_tgsi_get_dims(const struct tgsi_image *image,
|
||||
const struct tgsi_image_params *params,
|
||||
int dims[4])
|
||||
{
|
||||
struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
|
||||
struct pipe_image_view *iview;
|
||||
struct softpipe_resource *spr;
|
||||
int level;
|
||||
|
||||
if (params->unit > PIPE_MAX_SHADER_IMAGES)
|
||||
return;
|
||||
iview = &sp_img->sp_iview[params->unit];
|
||||
spr = (struct softpipe_resource *)iview->resource;
|
||||
if (!spr)
|
||||
return;
|
||||
|
||||
if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
|
||||
dims[0] = iview->u.buf.last_element - iview->u.buf.first_element + 1;
|
||||
dims[1] = dims[2] = dims[3] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
level = iview->u.tex.level;
|
||||
dims[0] = u_minify(spr->base.width0, level);
|
||||
switch (params->tgsi_tex_instr) {
|
||||
case TGSI_TEXTURE_1D_ARRAY:
|
||||
dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
|
||||
/* fallthrough */
|
||||
case TGSI_TEXTURE_1D:
|
||||
return;
|
||||
case TGSI_TEXTURE_2D_ARRAY:
|
||||
dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
|
||||
/* fallthrough */
|
||||
case TGSI_TEXTURE_2D:
|
||||
case TGSI_TEXTURE_CUBE:
|
||||
case TGSI_TEXTURE_RECT:
|
||||
dims[1] = u_minify(spr->base.height0, level);
|
||||
return;
|
||||
case TGSI_TEXTURE_3D:
|
||||
dims[1] = u_minify(spr->base.height0, level);
|
||||
dims[2] = u_minify(spr->base.depth0, level);
|
||||
return;
|
||||
case TGSI_TEXTURE_CUBE_ARRAY:
|
||||
dims[1] = u_minify(spr->base.height0, level);
|
||||
dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6;
|
||||
break;
|
||||
default:
|
||||
assert(!"unexpected texture target in sp_get_dims()");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct sp_tgsi_image *
|
||||
sp_create_tgsi_image(void)
|
||||
{
|
||||
struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image);
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
img->base.load = sp_tgsi_load;
|
||||
img->base.store = sp_tgsi_store;
|
||||
img->base.op = sp_tgsi_op;
|
||||
img->base.get_dims = sp_tgsi_get_dims;
|
||||
return img;
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SP_IMAGE_H
|
||||
#define SP_IMAGE_H
|
||||
#include "tgsi/tgsi_exec.h"
|
||||
|
||||
struct sp_tgsi_image
|
||||
{
|
||||
struct tgsi_image base;
|
||||
struct pipe_image_view sp_iview[PIPE_MAX_SHADER_IMAGES];
|
||||
};
|
||||
|
||||
struct sp_tgsi_image *
|
||||
sp_create_tgsi_image(void);
|
||||
|
||||
#endif
|
|
@ -56,6 +56,7 @@
|
|||
|
||||
|
||||
struct tgsi_sampler;
|
||||
struct tgsi_image;
|
||||
struct tgsi_exec_machine;
|
||||
struct vertex_info;
|
||||
|
||||
|
@ -81,7 +82,8 @@ struct sp_fragment_shader_variant
|
|||
|
||||
void (*prepare)(const struct sp_fragment_shader_variant *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
struct tgsi_sampler *sampler);
|
||||
struct tgsi_sampler *sampler,
|
||||
struct tgsi_image *image);
|
||||
|
||||
unsigned (*run)(const struct sp_fragment_shader_variant *shader,
|
||||
struct tgsi_exec_machine *machine,
|
||||
|
@ -149,6 +151,9 @@ softpipe_init_streamout_funcs(struct pipe_context *pipe);
|
|||
void
|
||||
softpipe_init_vertex_funcs(struct pipe_context *pipe);
|
||||
|
||||
void
|
||||
softpipe_init_image_funcs(struct pipe_context *pipe);
|
||||
|
||||
void
|
||||
softpipe_set_framebuffer_state(struct pipe_context *,
|
||||
const struct pipe_framebuffer_state *);
|
||||
|
|
|
@ -343,7 +343,8 @@ update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
|
|||
softpipe->fs_variant->prepare(softpipe->fs_variant,
|
||||
softpipe->fs_machine,
|
||||
(struct tgsi_sampler *) softpipe->
|
||||
tgsi.sampler[PIPE_SHADER_FRAGMENT]);
|
||||
tgsi.sampler[PIPE_SHADER_FRAGMENT],
|
||||
(struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT]);
|
||||
}
|
||||
else {
|
||||
softpipe->fs_variant = NULL;
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sp_context.h"
|
||||
#include "sp_state.h"
|
||||
#include "sp_image.h"
|
||||
|
||||
static void softpipe_set_shader_images(struct pipe_context *pipe,
|
||||
unsigned shader,
|
||||
unsigned start,
|
||||
unsigned num,
|
||||
struct pipe_image_view *images)
|
||||
{
|
||||
struct softpipe_context *softpipe = softpipe_context(pipe);
|
||||
unsigned i;
|
||||
assert(shader < PIPE_SHADER_TYPES);
|
||||
assert(start + num <= Elements(softpipe->sampler_views[shader]));
|
||||
|
||||
/* set the new images */
|
||||
for (i = 0; i < num; i++) {
|
||||
int idx = start + i;
|
||||
|
||||
if (images) {
|
||||
pipe_resource_reference(&softpipe->tgsi.image[shader]->sp_iview[idx].resource, images[i].resource);
|
||||
softpipe->tgsi.image[shader]->sp_iview[idx] = images[i];
|
||||
}
|
||||
else {
|
||||
pipe_resource_reference(&softpipe->tgsi.image[shader]->sp_iview[idx].resource, NULL);
|
||||
memset(&softpipe->tgsi.image[shader]->sp_iview[idx], 0, sizeof(struct pipe_image_view));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void softpipe_init_image_funcs(struct pipe_context *pipe)
|
||||
{
|
||||
pipe->set_shader_images = softpipe_set_shader_images;
|
||||
}
|
|
@ -270,9 +270,9 @@ softpipe_resource_get_handle(struct pipe_screen *screen,
|
|||
* Helper function to compute offset (in bytes) for a particular
|
||||
* texture level/face/slice from the start of the buffer.
|
||||
*/
|
||||
static unsigned
|
||||
sp_get_tex_image_offset(const struct softpipe_resource *spr,
|
||||
unsigned level, unsigned layer)
|
||||
unsigned
|
||||
softpipe_get_tex_image_offset(const struct softpipe_resource *spr,
|
||||
unsigned level, unsigned layer)
|
||||
{
|
||||
unsigned offset = spr->level_offset[level];
|
||||
|
||||
|
@ -422,7 +422,7 @@ softpipe_transfer_map(struct pipe_context *pipe,
|
|||
pt->stride = spr->stride[level];
|
||||
pt->layer_stride = spr->img_stride[level];
|
||||
|
||||
spt->offset = sp_get_tex_image_offset(spr, level, box->z);
|
||||
spt->offset = softpipe_get_tex_image_offset(spr, level, box->z);
|
||||
|
||||
spt->offset +=
|
||||
box->y / util_format_get_blockheight(format) * spt->base.stride +
|
||||
|
|
|
@ -116,5 +116,7 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen);
|
|||
extern void
|
||||
softpipe_init_texture_funcs(struct pipe_context *pipe);
|
||||
|
||||
|
||||
unsigned
|
||||
softpipe_get_tex_image_offset(const struct softpipe_resource *spr,
|
||||
unsigned level, unsigned layer);
|
||||
#endif /* SP_TEXTURE */
|
||||
|
|
Loading…
Reference in New Issue