summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2015-05-02 16:58:24 +0300
committerFrancisco Jerez <currojerez@riseup.net>2015-05-12 17:47:24 +0300
commite52abb13101c75c0ae2d7eacaa9bfc49a7279928 (patch)
tree41f487f7070631e6d6829bb72c122eeb92e618b3
parent88e8ad27729767d4b20812df6f0b06beec306502 (diff)
i965: Implement surface state set-up for shader images.
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h2
-rw-r--r--src/mesa/drivers/dri/i965/brw_surface_formats.c112
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c77
3 files changed, 191 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 2dcc23c5fc6..c55dcec3f27 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1741,6 +1741,8 @@ void brw_upload_abo_surfaces(struct brw_context *brw,
bool brw_render_target_supported(struct brw_context *brw,
struct gl_renderbuffer *rb);
uint32_t brw_depth_format(struct brw_context *brw, mesa_format format);
+mesa_format brw_lower_mesa_image_format(const struct brw_device_info *devinfo,
+ mesa_format format);
/* brw_performance_monitor.c */
void brw_init_performance_monitors(struct brw_context *brw);
diff --git a/src/mesa/drivers/dri/i965/brw_surface_formats.c b/src/mesa/drivers/dri/i965/brw_surface_formats.c
index 016f87a4c2a..12cc717fa11 100644
--- a/src/mesa/drivers/dri/i965/brw_surface_formats.c
+++ b/src/mesa/drivers/dri/i965/brw_surface_formats.c
@@ -805,3 +805,115 @@ brw_depth_format(struct brw_context *brw, mesa_format format)
unreachable("Unexpected depth format.");
}
}
+
+mesa_format
+brw_lower_mesa_image_format(const struct brw_device_info *devinfo,
+ mesa_format format)
+{
+ switch (format) {
+ case MESA_FORMAT_RGBA_UINT32:
+ case MESA_FORMAT_RGBA_SINT32:
+ case MESA_FORMAT_RGBA_FLOAT32:
+ /* Fail... We'll have to fall back to untyped surface access for all
+ * 128 bpp formats.
+ */
+ return MESA_FORMAT_RGBA_UINT32;
+
+ case MESA_FORMAT_RGBA_UINT16:
+ case MESA_FORMAT_RGBA_SINT16:
+ case MESA_FORMAT_RGBA_FLOAT16:
+ case MESA_FORMAT_RGBA_UNORM16:
+ case MESA_FORMAT_RGBA_SNORM16:
+ case MESA_FORMAT_RG_UINT32:
+ case MESA_FORMAT_RG_SINT32:
+ case MESA_FORMAT_RG_FLOAT32:
+ /* HSW and later support the RGBA_UINT16 format natively and handle the
+ * pixel packing, unpacking and type conversion in the shader for other
+ * 64 bpp formats. IVB falls back to untyped.
+ */
+ return (devinfo->gen >= 8 || devinfo->is_haswell ?
+ MESA_FORMAT_RGBA_UINT16 : MESA_FORMAT_RG_UINT32);
+
+ case MESA_FORMAT_RGBA_UINT8:
+ case MESA_FORMAT_RGBA_SINT8:
+ case MESA_FORMAT_R8G8B8A8_UNORM:
+ case MESA_FORMAT_R8G8B8A8_SNORM:
+ /* HSW and later support the RGBA_UINT8 format natively, type conversion
+ * to other formats is handled in the shader. IVB uses R_UINT32 and
+ * handles the pixel packing, unpacking and type conversion in the
+ * shader.
+ */
+ return (devinfo->gen >= 8 || devinfo->is_haswell ?
+ MESA_FORMAT_RGBA_UINT8 : MESA_FORMAT_R_UINT32);
+
+ case MESA_FORMAT_RG_UINT16:
+ case MESA_FORMAT_RG_SINT16:
+ case MESA_FORMAT_RG_FLOAT16:
+ case MESA_FORMAT_R16G16_UNORM:
+ case MESA_FORMAT_R16G16_SNORM:
+ /* HSW and later support the RG_UINT16 format natively, type conversion
+ * to other formats is handled in the shader. IVB uses R_UINT32 and
+ * handles the pixel packing, unpacking and type conversion in the
+ * shader.
+ */
+ return (devinfo->gen >= 8 || devinfo->is_haswell ?
+ MESA_FORMAT_RG_UINT16 : MESA_FORMAT_R_UINT32);
+
+ case MESA_FORMAT_R10G10B10A2_UINT:
+ case MESA_FORMAT_R10G10B10A2_UNORM:
+ case MESA_FORMAT_R11G11B10_FLOAT:
+ case MESA_FORMAT_R_UINT32:
+ /* Neither the 2/10/10/10 nor the 11/11/10 packed formats are supported
+ * by the hardware. Use R_UINT32 and handle the pixel packing,
+ * unpacking, and type conversion in the shader.
+ */
+ return MESA_FORMAT_R_UINT32;
+
+ case MESA_FORMAT_R_SINT32:
+ return MESA_FORMAT_R_SINT32;
+
+ case MESA_FORMAT_R_FLOAT32:
+ return MESA_FORMAT_R_FLOAT32;
+
+ case MESA_FORMAT_RG_UINT8:
+ case MESA_FORMAT_RG_SINT8:
+ case MESA_FORMAT_R8G8_UNORM:
+ case MESA_FORMAT_R8G8_SNORM:
+ /* HSW and later support the RG_UINT8 format natively, type conversion
+ * to other formats is handled in the shader. IVB uses R_UINT16 and
+ * handles the pixel packing, unpacking and type conversion in the
+ * shader. Note that this relies on the undocumented behavior that
+ * typed reads from R_UINT16 surfaces actually do a 32-bit misaligned
+ * read on IVB. The alternative would be to use two surface state
+ * entries with different formats for each image, one for reading (using
+ * R_UINT32) and another one for writing (using RG_UINT8), but that
+ * would complicate the shaders we generate even more.
+ */
+ return (devinfo->gen >= 8 || devinfo->is_haswell ?
+ MESA_FORMAT_RG_UINT8 : MESA_FORMAT_R_UINT16);
+
+ case MESA_FORMAT_R_UINT16:
+ case MESA_FORMAT_R_FLOAT16:
+ case MESA_FORMAT_R_SINT16:
+ case MESA_FORMAT_R_UNORM16:
+ case MESA_FORMAT_R_SNORM16:
+ /* HSW and later support the R_UINT16 format natively, type conversion
+ * to other formats is handled in the shader. IVB relies on the same
+ * undocumented behavior described above.
+ */
+ return MESA_FORMAT_R_UINT16;
+
+ case MESA_FORMAT_R_UINT8:
+ case MESA_FORMAT_R_SINT8:
+ case MESA_FORMAT_R_UNORM8:
+ case MESA_FORMAT_R_SNORM8:
+ /* HSW and later support the R_UINT8 format natively, type conversion to
+ * other formats is handled in the shader. IVB relies on the same
+ * undocumented behavior described above.
+ */
+ return MESA_FORMAT_R_UINT8;
+
+ default:
+ unreachable("Not reached");
+ }
+}
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 160dd2f6c62..367caa82088 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -1022,6 +1022,83 @@ const struct brw_tracked_state brw_cs_abo_surfaces = {
.emit = brw_upload_cs_abo_surfaces,
};
+static uint32_t
+get_image_format(struct brw_context *brw, mesa_format format, GLenum access)
+{
+ if (access == GL_WRITE_ONLY) {
+ return brw_format_for_mesa_format(format);
+ } else {
+ /* Typed surface reads support a very limited subset of the shader
+ * image formats. Translate it into the closest format the
+ * hardware supports.
+ */
+ if (_mesa_get_format_bytes(format) >= 16 ||
+ (_mesa_get_format_bytes(format) >= 8 &&
+ (brw->gen == 7 && !brw->is_haswell)))
+ return BRW_SURFACEFORMAT_RAW;
+ else
+ return brw_format_for_mesa_format(
+ brw_lower_mesa_image_format(brw->intelScreen->devinfo, format));
+ }
+}
+
+static void
+update_image_surface(struct brw_context *brw,
+ struct gl_image_unit *u,
+ GLenum access,
+ unsigned surface_idx,
+ uint32_t *surf_offset,
+ struct brw_image_param *param)
+{
+ if (u->_Valid) {
+ struct gl_texture_object *obj = u->TexObj;
+ const unsigned format = get_image_format(brw, u->_ActualFormat, access);
+
+ if (obj->Target == GL_TEXTURE_BUFFER) {
+ struct intel_buffer_object *intel_obj =
+ intel_buffer_object(obj->BufferObject);
+ const unsigned texel_size = (format == BRW_SURFACEFORMAT_RAW ? 1 :
+ _mesa_get_format_bytes(u->_ActualFormat));
+
+ brw->vtbl.emit_buffer_surface_state(
+ brw, surf_offset, intel_obj->buffer, obj->BufferOffset,
+ format, intel_obj->Base.Size / texel_size, texel_size,
+ access != GL_READ_ONLY);
+
+ } else {
+ struct intel_texture_object *intel_obj = intel_texture_object(obj);
+ struct intel_mipmap_tree *mt = intel_obj->mt;
+
+ if (format == BRW_SURFACEFORMAT_RAW) {
+ brw->vtbl.emit_buffer_surface_state(
+ brw, surf_offset, mt->bo, mt->offset,
+ format, mt->bo->size - mt->offset, 1 /* pitch */,
+ access != GL_READ_ONLY);
+
+ } else {
+ const unsigned min_layer = obj->MinLayer + u->Layer;
+ const unsigned min_level = obj->MinLevel + u->Level;
+ const unsigned num_layers = (!u->Layered ? 1 :
+ obj->Target == GL_TEXTURE_CUBE_MAP ? 6 :
+ mt->logical_depth0);
+ const GLenum target = (obj->Target == GL_TEXTURE_CUBE_MAP ||
+ obj->Target == GL_TEXTURE_CUBE_MAP_ARRAY ?
+ GL_TEXTURE_2D_ARRAY : obj->Target);
+
+ brw->vtbl.emit_texture_surface_state(
+ brw, mt, target,
+ min_layer, min_layer + num_layers,
+ min_level, min_level + 1,
+ format, SWIZZLE_XYZW,
+ surf_offset, access != GL_READ_ONLY, false);
+ }
+ }
+
+ } else {
+ brw->vtbl.emit_null_surface_state(brw, 1, 1, 1, surf_offset);
+ }
+}
+
void
gen4_init_vtable_surface_functions(struct brw_context *brw)
{