aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 24c7b100fea..3430734a9dd 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -1767,16 +1767,43 @@ static uint32_t si_translate_buffer_numformat(struct pipe_screen *screen,
}
}
-static bool si_is_vertex_format_supported(struct pipe_screen *screen, enum pipe_format format)
+static unsigned si_is_vertex_format_supported(struct pipe_screen *screen,
+ enum pipe_format format,
+ unsigned usage)
{
const struct util_format_description *desc;
int first_non_void;
unsigned data_format;
+ assert((usage & ~(PIPE_BIND_SHADER_IMAGE |
+ PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_VERTEX_BUFFER)) == 0);
+
desc = util_format_description(format);
+
+ /* There are no native 8_8_8 or 16_16_16 data formats, and we currently
+ * select 8_8_8_8 and 16_16_16_16 instead. This works reasonably well
+ * for read-only access (with caveats surrounding bounds checks), but
+ * obviously fails for write access which we have to implement for
+ * shader images. Luckily, OpenGL doesn't expect this to be supported
+ * anyway, and so the only impact is on PBO uploads / downloads, which
+ * shouldn't be expected to be fast for GL_RGB anyway.
+ */
+ if (desc->block.bits == 3 * 8 ||
+ desc->block.bits == 3 * 16) {
+ if (usage & (PIPE_BIND_SHADER_IMAGE | PIPE_BIND_SAMPLER_VIEW)) {
+ usage &= ~(PIPE_BIND_SHADER_IMAGE | PIPE_BIND_SAMPLER_VIEW);
+ if (!usage)
+ return 0;
+ }
+ }
+
first_non_void = util_format_get_first_non_void_channel(format);
data_format = si_translate_buffer_dataformat(screen, desc, first_non_void);
- return data_format != V_008F0C_BUF_DATA_FORMAT_INVALID;
+ if (data_format == V_008F0C_BUF_DATA_FORMAT_INVALID)
+ return 0;
+
+ return usage;
}
static bool si_is_colorbuffer_format_supported(enum pipe_format format)
@@ -1831,9 +1858,9 @@ static boolean si_is_format_supported(struct pipe_screen *screen,
if (usage & (PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_SHADER_IMAGE)) {
if (target == PIPE_BUFFER) {
- if (si_is_vertex_format_supported(screen, format))
- retval |= usage & (PIPE_BIND_SAMPLER_VIEW |
- PIPE_BIND_SHADER_IMAGE);
+ retval |= si_is_vertex_format_supported(
+ screen, format, usage & (PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_SHADER_IMAGE));
} else {
if (si_is_sampler_format_supported(screen, format))
retval |= usage & (PIPE_BIND_SAMPLER_VIEW |
@@ -1862,9 +1889,9 @@ static boolean si_is_format_supported(struct pipe_screen *screen,
retval |= PIPE_BIND_DEPTH_STENCIL;
}
- if ((usage & PIPE_BIND_VERTEX_BUFFER) &&
- si_is_vertex_format_supported(screen, format)) {
- retval |= PIPE_BIND_VERTEX_BUFFER;
+ if (usage & PIPE_BIND_VERTEX_BUFFER) {
+ retval |= si_is_vertex_format_supported(screen, format,
+ PIPE_BIND_VERTEX_BUFFER);
}
if ((usage & PIPE_BIND_LINEAR) &&