diff options
Diffstat (limited to 'src/gallium/drivers/v3d')
-rw-r--r-- | src/gallium/drivers/v3d/v3d_context.h | 14 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3d_screen.c | 9 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3d_uniforms.c | 68 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3dx_draw.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3dx_state.c | 94 |
5 files changed, 196 insertions, 2 deletions
diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 686ecfa8024..136d8506597 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -58,6 +58,7 @@ void v3d_job_add_bo(struct v3d_job *job, struct v3d_bo *bo); #define VC5_DIRTY_ZSA (1 << 2) #define VC5_DIRTY_FRAGTEX (1 << 3) #define VC5_DIRTY_VERTTEX (1 << 4) +#define VC5_DIRTY_SHADER_IMAGE (1 << 5) #define VC5_DIRTY_BLEND_COLOR (1 << 7) #define VC5_DIRTY_STENCIL_REF (1 << 8) @@ -222,6 +223,18 @@ enum v3d_ez_state { VC5_EZ_DISABLED, }; +struct v3d_image_view { + struct pipe_image_view base; + /* V3D 4.x texture shader state struct */ + struct pipe_resource *tex_state; + uint32_t tex_state_offset; +}; + +struct v3d_shaderimg_stateobj { + struct v3d_image_view si[PIPE_MAX_SHADER_IMAGES]; + uint32_t enabled_mask; +}; + /** * A complete bin/render job. * @@ -440,6 +453,7 @@ struct v3d_context { struct pipe_clip_state clip; struct pipe_viewport_state viewport; struct v3d_ssbo_stateobj ssbo[PIPE_SHADER_TYPES]; + struct v3d_shaderimg_stateobj shaderimg[PIPE_SHADER_TYPES]; struct v3d_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; struct v3d_texture_stateobj tex[PIPE_SHADER_TYPES]; struct v3d_vertexbuf_stateobj vertexbuf; diff --git a/src/gallium/drivers/v3d/v3d_screen.c b/src/gallium/drivers/v3d/v3d_screen.c index dd5eda87e8f..bee036a96d3 100644 --- a/src/gallium/drivers/v3d/v3d_screen.c +++ b/src/gallium/drivers/v3d/v3d_screen.c @@ -240,6 +240,8 @@ static int v3d_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum pipe_shader_cap param) { + struct v3d_screen *screen = v3d_screen(pscreen); + if (shader != PIPE_SHADER_VERTEX && shader != PIPE_SHADER_FRAGMENT) { return 0; @@ -298,12 +300,17 @@ v3d_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, return 1; case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: - case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: return VC5_MAX_TEXTURE_SAMPLERS; case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: return PIPE_MAX_SHADER_BUFFERS; + case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: + if (screen->devinfo.ver < 41) + return 0; + else + return PIPE_MAX_SHADER_IMAGES; + case PIPE_SHADER_CAP_PREFERRED_IR: return PIPE_SHADER_IR_NIR; case PIPE_SHADER_CAP_SUPPORTED_IRS: diff --git a/src/gallium/drivers/v3d/v3d_uniforms.c b/src/gallium/drivers/v3d/v3d_uniforms.c index 5d907726349..5a3286013cd 100644 --- a/src/gallium/drivers/v3d/v3d_uniforms.c +++ b/src/gallium/drivers/v3d/v3d_uniforms.c @@ -71,6 +71,30 @@ get_texture_size(struct v3d_texture_stateobj *texstate, } } +static uint32_t +get_image_size(struct v3d_shaderimg_stateobj *shaderimg, + enum quniform_contents contents, + uint32_t data) +{ + struct v3d_image_view *image = &shaderimg->si[data]; + + switch (contents) { + case QUNIFORM_IMAGE_WIDTH: + return u_minify(image->base.resource->width0, + image->base.u.tex.level); + case QUNIFORM_IMAGE_HEIGHT: + return u_minify(image->base.resource->height0, + image->base.u.tex.level); + case QUNIFORM_IMAGE_DEPTH: + return u_minify(image->base.resource->depth0, + image->base.u.tex.level); + case QUNIFORM_IMAGE_ARRAY_SIZE: + return image->base.resource->array_size; + default: + unreachable("Bad texture size field"); + } +} + static struct v3d_bo * v3d_upload_ubo(struct v3d_context *v3d, struct v3d_compiled_shader *shader, @@ -158,6 +182,27 @@ write_tmu_p0(struct v3d_job *job, v3d_job_add_bo(job, rsc->bo); } +static void +write_image_tmu_p0(struct v3d_job *job, + struct v3d_cl_out **uniforms, + struct v3d_shaderimg_stateobj *img, + uint32_t data) +{ + /* Extract the image unit from the top bits, and the compiler's + * packed p0 from the bottom. + */ + uint32_t unit = data >> 24; + uint32_t p0 = data & 0x00ffffff; + + struct v3d_image_view *iview = &img->si[unit]; + struct v3d_resource *rsc = v3d_resource(iview->base.resource); + + cl_aligned_reloc(&job->indirect, uniforms, + v3d_resource(iview->tex_state)->bo, + iview->tex_state_offset | p0); + v3d_job_add_bo(job, rsc->bo); +} + /** Writes the V3D 4.x TMU configuration parameter 1. */ static void write_tmu_p1(struct v3d_job *job, @@ -232,6 +277,11 @@ v3d_write_uniforms(struct v3d_context *v3d, struct v3d_compiled_shader *shader, write_tmu_p1(job, &uniforms, texstate, data); break; + case QUNIFORM_IMAGE_TMU_CONFIG_P0: + write_image_tmu_p0(job, &uniforms, + &v3d->shaderimg[stage], data); + break; + case QUNIFORM_TEXTURE_CONFIG_P1: write_texture_p1(job, &uniforms, texstate, data); @@ -256,6 +306,16 @@ v3d_write_uniforms(struct v3d_context *v3d, struct v3d_compiled_shader *shader, data)); break; + case QUNIFORM_IMAGE_WIDTH: + case QUNIFORM_IMAGE_HEIGHT: + case QUNIFORM_IMAGE_DEPTH: + case QUNIFORM_IMAGE_ARRAY_SIZE: + cl_aligned_u32(&uniforms, + get_image_size(&v3d->shaderimg[stage], + uinfo->contents[i], + data)); + break; + case QUNIFORM_ALPHA_REF: cl_aligned_f(&uniforms, v3d->zsa->base.alpha.ref_value); @@ -382,6 +442,14 @@ v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader *shader) dirty |= VC5_DIRTY_SSBO; break; + case QUNIFORM_IMAGE_TMU_CONFIG_P0: + case QUNIFORM_IMAGE_WIDTH: + case QUNIFORM_IMAGE_HEIGHT: + case QUNIFORM_IMAGE_DEPTH: + case QUNIFORM_IMAGE_ARRAY_SIZE: + dirty |= VC5_DIRTY_SHADER_IMAGE; + break; + case QUNIFORM_ALPHA_REF: dirty |= VC5_DIRTY_ZSA; break; diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 7f111bbe75f..7ec687031d6 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -148,6 +148,13 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx, if (cb->buffer) v3d_flush_jobs_writing_resource(v3d, cb->buffer); } + + /* Flush writes to our image views */ + foreach_bit(i, v3d->shaderimg[s].enabled_mask) { + struct v3d_image_view *view = &v3d->shaderimg[s].si[i]; + + v3d_flush_jobs_writing_resource(v3d, view->base.resource); + } } static void @@ -487,6 +494,12 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) v3d->ssbo[s].sb[i].buffer); job->tmu_dirty_rcl = true; } + + foreach_bit(i, v3d->shaderimg[s].enabled_mask) { + v3d_job_add_write_resource(job, + v3d->shaderimg[s].si[i].base.resource); + job->tmu_dirty_rcl = true; + } } /* Get space to emit our draw call into the BCL, using a branch to diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c index 7ea5dabbe1f..5377f6173c3 100644 --- a/src/gallium/drivers/v3d/v3dx_state.c +++ b/src/gallium/drivers/v3d/v3dx_state.c @@ -884,7 +884,7 @@ v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, tex.srgb = false; } else { tex.texture_type = v3d_get_tex_format(&screen->devinfo, - cso->format); + cso->format); } }; @@ -1033,6 +1033,97 @@ v3d_set_shader_buffers(struct pipe_context *pctx, v3d->dirty |= VC5_DIRTY_SSBO; } +static void +v3d_create_image_view_texture_shader_state(struct v3d_context *v3d, + struct v3d_shaderimg_stateobj *so, + int img) +{ +#if V3D_VERSION >= 40 + struct v3d_image_view *iview = &so->si[img]; + + void *map; + u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE), + 32, + &iview->tex_state_offset, + &iview->tex_state, + &map); + + struct pipe_resource *prsc = iview->base.resource; + + v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { + v3d_setup_texture_shader_state(&tex, prsc, + iview->base.u.tex.level, + iview->base.u.tex.level, + iview->base.u.tex.first_layer, + iview->base.u.tex.last_layer); + + tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X); + tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y); + tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z); + tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W); + + tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo, + iview->base.format); + }; +#else /* V3D_VERSION < 40 */ + /* V3D 3.x doesn't use support shader image load/store operations on + * textures, so it would get lowered in the shader to general memory + * acceses. + */ +#endif +} + +static void +v3d_set_shader_images(struct pipe_context *pctx, + enum pipe_shader_type shader, + unsigned start, unsigned count, + const struct pipe_image_view *images) +{ + struct v3d_context *v3d = v3d_context(pctx); + struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader]; + + if (images) { + for (unsigned i = 0; i < count; i++) { + unsigned n = i + start; + struct v3d_image_view *iview = &so->si[n]; + + if ((iview->base.resource == images[i].resource) && + (iview->base.format == images[i].format) && + (iview->base.access == images[i].access) && + !memcmp(&iview->base.u, &images[i].u, + sizeof(iview->base.u))) + continue; + + util_copy_image_view(&iview->base, &images[i]); + + if (iview->base.resource) { + so->enabled_mask |= 1 << n; + v3d_create_image_view_texture_shader_state(v3d, + so, + n); + } else { + so->enabled_mask &= ~(1 << n); + pipe_resource_reference(&iview->tex_state, NULL); + } + } + } else { + for (unsigned i = 0; i < count; i++) { + unsigned n = i + start; + struct v3d_image_view *iview = &so->si[n]; + + pipe_resource_reference(&iview->base.resource, NULL); + pipe_resource_reference(&iview->tex_state, NULL); + } + + if (count == 32) + so->enabled_mask = 0; + else + so->enabled_mask &= ~(((1 << count) - 1) << start); + } + + v3d->dirty |= VC5_DIRTY_SHADER_IMAGE; +} + void v3dX(state_init)(struct pipe_context *pctx) { @@ -1073,6 +1164,7 @@ v3dX(state_init)(struct pipe_context *pctx) pctx->set_sampler_views = v3d_set_sampler_views; pctx->set_shader_buffers = v3d_set_shader_buffers; + pctx->set_shader_images = v3d_set_shader_images; pctx->create_stream_output_target = v3d_create_stream_output_target; pctx->stream_output_target_destroy = v3d_stream_output_target_destroy; |