*
**************************************************************************/
-#include "main/imports.h"
+
#include "main/shaderimage.h"
#include "program/prog_parameter.h"
#include "program/prog_print.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_surface.h"
+#include "cso_cache/cso_context.h"
+#include "st_cb_bufferobjects.h"
#include "st_cb_texture.h"
#include "st_debug.h"
#include "st_texture.h"
#include "st_program.h"
#include "st_format.h"
-static void
-st_bind_images(struct st_context *st, struct gl_shader *shader,
- unsigned shader_type)
+/**
+ * Convert a gl_image_unit object to a pipe_image_view object.
+ */
+void
+st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
+ struct pipe_image_view *img, unsigned shader_access)
{
- unsigned i;
- struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
- struct gl_program_constants *c;
+ struct st_texture_object *stObj = st_texture_object(u->TexObj);
+
+ img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
+
+ switch (u->Access) {
+ case GL_READ_ONLY:
+ img->access = PIPE_IMAGE_ACCESS_READ;
+ break;
+ case GL_WRITE_ONLY:
+ img->access = PIPE_IMAGE_ACCESS_WRITE;
+ break;
+ case GL_READ_WRITE:
+ img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
+ break;
+ default:
+ unreachable("bad gl_image_unit::Access");
+ }
- if (!shader || !st->pipe->set_shader_images)
- return;
+ switch (shader_access) {
+ case GL_NONE:
+ img->shader_access = 0;
+ break;
+ case GL_READ_ONLY:
+ img->shader_access = PIPE_IMAGE_ACCESS_READ;
+ break;
+ case GL_WRITE_ONLY:
+ img->shader_access = PIPE_IMAGE_ACCESS_WRITE;
+ break;
+ case GL_READ_WRITE:
+ img->shader_access = PIPE_IMAGE_ACCESS_READ_WRITE;
+ break;
+ default:
+ unreachable("bad gl_image_unit::Access");
+ }
- c = &st->ctx->Const.Program[shader->Stage];
+ if (stObj->base.Target == GL_TEXTURE_BUFFER) {
+ struct st_buffer_object *stbuf =
+ st_buffer_object(stObj->base.BufferObject);
+ unsigned base, size;
- for (i = 0; i < shader->NumImages; i++) {
- struct gl_image_unit *u = &st->ctx->ImageUnits[shader->ImageUnits[i]];
- struct st_texture_object *stObj = st_texture_object(u->TexObj);
- struct pipe_image_view *img = &images[i];
+ if (!stbuf || !stbuf->buffer) {
+ memset(img, 0, sizeof(*img));
+ return;
+ }
+ struct pipe_resource *buf = stbuf->buffer;
+
+ base = stObj->base.BufferOffset;
+ assert(base < buf->width0);
+ size = MIN2(buf->width0 - base, (unsigned)stObj->base.BufferSize);
- if (!_mesa_is_image_unit_valid(st->ctx, u) ||
- !st_finalize_texture(st->ctx, st->pipe, u->TexObj) ||
+ img->resource = stbuf->buffer;
+ img->u.buf.offset = base;
+ img->u.buf.size = size;
+ } else {
+ if (!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
!stObj->pt) {
memset(img, 0, sizeof(*img));
- continue;
+ return;
}
img->resource = stObj->pt;
- img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
- if (stObj->pt->target == PIPE_BUFFER) {
- unsigned base, size;
- unsigned f, n;
- const struct util_format_description *desc
- = util_format_description(img->format);
-
- base = stObj->base.BufferOffset;
- assert(base < stObj->pt->width0);
- size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
-
- f = (base / (desc->block.bits / 8)) * desc->block.width;
- n = (size / (desc->block.bits / 8)) * desc->block.width;
- assert(n > 0);
- img->u.buf.first_element = f;
- img->u.buf.last_element = f + (n - 1);
- } else {
- img->u.tex.level = u->Level + stObj->base.MinLevel;
- if (stObj->pt->target == PIPE_TEXTURE_3D) {
- if (u->Layered) {
- img->u.tex.first_layer = 0;
- img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
- } else {
- img->u.tex.first_layer = u->_Layer;
- img->u.tex.last_layer = u->_Layer;
- }
+ img->u.tex.level = u->Level + stObj->base.MinLevel;
+ assert(img->u.tex.level <= img->resource->last_level);
+ if (stObj->pt->target == PIPE_TEXTURE_3D) {
+ if (u->Layered) {
+ img->u.tex.first_layer = 0;
+ img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
} else {
- img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
- img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
- if (u->Layered && img->resource->array_size > 1) {
- if (stObj->base.Immutable)
- img->u.tex.last_layer += stObj->base.NumLayers - 1;
- else
- img->u.tex.last_layer += img->resource->array_size - 1;
- }
+ img->u.tex.first_layer = u->_Layer;
+ img->u.tex.last_layer = u->_Layer;
+ }
+ } else {
+ img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
+ img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
+ if (u->Layered && img->resource->array_size > 1) {
+ if (stObj->base.Immutable)
+ img->u.tex.last_layer += stObj->base.NumLayers - 1;
+ else
+ img->u.tex.last_layer += img->resource->array_size - 1;
}
}
}
- st->pipe->set_shader_images(st->pipe, shader_type, 0, shader->NumImages,
- images);
- /* clear out any stale shader images */
- if (shader->NumImages < c->MaxImageUniforms)
- st->pipe->set_shader_images(
- st->pipe, shader_type,
- shader->NumImages,
- c->MaxImageUniforms - shader->NumImages,
- NULL);
}
-static void bind_vs_images(struct st_context *st)
+/**
+ * Get a pipe_image_view object from an image unit.
+ */
+void
+st_convert_image_from_unit(const struct st_context *st,
+ struct pipe_image_view *img,
+ GLuint imgUnit,
+ unsigned shader_access)
{
- struct gl_shader_program *prog =
- st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
+ struct gl_image_unit *u = &st->ctx->ImageUnits[imgUnit];
- if (!prog)
+ if (!_mesa_is_image_unit_valid(st->ctx, u)) {
+ memset(img, 0, sizeof(*img));
return;
+ }
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_VERTEX], PIPE_SHADER_VERTEX);
+ st_convert_image(st, u, img, shader_access);
}
-const struct st_tracked_state st_bind_vs_images = {
- "st_bind_vs_images",
- {
- 0,
- ST_NEW_VERTEX_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_vs_images
-};
-
-static void bind_fs_images(struct st_context *st)
+static void
+st_bind_images(struct st_context *st, struct gl_program *prog,
+ enum pipe_shader_type shader_type)
{
- struct gl_shader_program *prog =
- st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
+ unsigned i;
+ struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
+ struct gl_program_constants *c;
- if (!prog)
+ if (!prog || !st->pipe->set_shader_images)
return;
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT], PIPE_SHADER_FRAGMENT);
-}
+ c = &st->ctx->Const.Program[prog->info.stage];
-const struct st_tracked_state st_bind_fs_images = {
- "st_bind_fs_images",
- {
- 0,
- ST_NEW_FRAGMENT_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_fs_images
-};
+ for (i = 0; i < prog->info.num_images; i++) {
+ struct pipe_image_view *img = &images[i];
-static void bind_gs_images(struct st_context *st)
+ st_convert_image_from_unit(st, img, prog->sh.ImageUnits[i],
+ prog->sh.ImageAccess[i]);
+ }
+ cso_set_shader_images(st->cso_context, shader_type, 0,
+ prog->info.num_images, images);
+ /* clear out any stale shader images */
+ if (prog->info.num_images < c->MaxImageUniforms)
+ cso_set_shader_images(
+ st->cso_context, shader_type, prog->info.num_images,
+ c->MaxImageUniforms - prog->info.num_images, NULL);
+}
+
+void st_bind_vs_images(struct st_context *st)
{
- struct gl_shader_program *prog =
- st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
+ struct gl_program *prog =
+ st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
- if (!prog)
- return;
+ st_bind_images(st, prog, PIPE_SHADER_VERTEX);
+}
+
+void st_bind_fs_images(struct st_context *st)
+{
+ struct gl_program *prog =
+ st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_GEOMETRY], PIPE_SHADER_GEOMETRY);
+ st_bind_images(st, prog, PIPE_SHADER_FRAGMENT);
}
-const struct st_tracked_state st_bind_gs_images = {
- "st_bind_gs_images",
- {
- 0,
- ST_NEW_GEOMETRY_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_gs_images
-};
+void st_bind_gs_images(struct st_context *st)
+{
+ struct gl_program *prog =
+ st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
+
+ st_bind_images(st, prog, PIPE_SHADER_GEOMETRY);
+}
-static void bind_tcs_images(struct st_context *st)
+void st_bind_tcs_images(struct st_context *st)
{
- struct gl_shader_program *prog =
+ struct gl_program *prog =
st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
- if (!prog)
- return;
-
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_TESS_CTRL], PIPE_SHADER_TESS_CTRL);
+ st_bind_images(st, prog, PIPE_SHADER_TESS_CTRL);
}
-const struct st_tracked_state st_bind_tcs_images = {
- "st_bind_tcs_images",
- {
- 0,
- ST_NEW_TESSCTRL_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_tcs_images
-};
-
-static void bind_tes_images(struct st_context *st)
+void st_bind_tes_images(struct st_context *st)
{
- struct gl_shader_program *prog =
+ struct gl_program *prog =
st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
- if (!prog)
- return;
-
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_TESS_EVAL], PIPE_SHADER_TESS_EVAL);
+ st_bind_images(st, prog, PIPE_SHADER_TESS_EVAL);
}
-const struct st_tracked_state st_bind_tes_images = {
- "st_bind_tes_images",
- {
- 0,
- ST_NEW_TESSEVAL_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_tes_images
-};
-
-static void bind_cs_images(struct st_context *st)
+void st_bind_cs_images(struct st_context *st)
{
- struct gl_shader_program *prog =
+ struct gl_program *prog =
st->ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
- if (!prog)
- return;
-
- st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_COMPUTE], PIPE_SHADER_COMPUTE);
+ st_bind_images(st, prog, PIPE_SHADER_COMPUTE);
}
-
-const struct st_tracked_state st_bind_cs_images = {
- "st_bind_cs_images",
- {
- 0,
- ST_NEW_COMPUTE_PROGRAM | ST_NEW_IMAGE_UNITS,
- },
- bind_cs_images
-};