From fccfb7b16512a36424370dc1942cdedd3d1c208a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 8 Jun 2010 23:45:11 +0200 Subject: [PATCH] r300g: skip rendering for unsupported vertex formats instead of aborting The next step is to replace skipping by an actual fallback. --- src/gallium/drivers/r300/r300_context.h | 13 +++ src/gallium/drivers/r300/r300_emit.c | 16 +-- src/gallium/drivers/r300/r300_render.c | 12 +- src/gallium/drivers/r300/r300_state.c | 146 +++++++++++------------- 4 files changed, 93 insertions(+), 94 deletions(-) diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 48ec52d26cf..cca11f80452 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -326,6 +326,17 @@ struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + /* If (velem[i].src_format != hw_format[i]), the vertex buffer + * referenced by this vertex element cannot be used for rendering and + * its vertex data must be translated to hw_format[i]. */ + enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; + unsigned hw_format_size[PIPE_MAX_ATTRIBS]; + + /* This might mean two things: + * - src_format != hw_format, as discussed above. + * - src_offset % 4 != 0. */ + boolean incompatible_layout; + struct r300_vertex_stream_state vertex_stream; }; @@ -434,6 +445,8 @@ struct r300_context { int sprite_coord_enable; /* Whether two-sided color selection is enabled (AKA light_twoside). */ boolean two_sided_color; + /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */ + boolean incompatible_vb_layout; /* upload managers */ struct u_upload_mgr *upload_vb; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index c329c0f30ff..dd9bca88f10 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -821,19 +821,11 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) struct pipe_vertex_element *velem = r300->velems->velem; struct r300_buffer *buf; int i; + unsigned *hw_format_size = r300->velems->hw_format_size; unsigned size1, size2, aos_count = r300->velems->count; unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); - for (i = 0; i < aos_count; i++) { - if ((vbuf[velem[i].vertex_buffer_index].buffer_offset + velem[i].src_offset) % 4 != 0) { - /* XXX We must align the buffer. */ - assert(0); - fprintf(stderr, "r300: Unaligned vertex buffer offsets aren't supported, aborting..\n"); - abort(); - } - } - BEGIN_CS(2 + packet_size + aos_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); @@ -841,8 +833,8 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) for (i = 0; i < aos_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; - size1 = util_format_get_blocksize(velem[i].src_format); - size2 = util_format_get_blocksize(velem[i+1].src_format); + size1 = hw_format_size[i]; + size2 = hw_format_size[i+1]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); @@ -852,7 +844,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) if (aos_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; - size1 = util_format_get_blocksize(velem[i].src_format); + size1 = hw_format_size[i]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 23caaa54730..80dea8be989 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -333,7 +333,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; offset[i] = velem->src_offset / 4; - size[i] = util_format_get_blocksize(velem->src_format) / 4; + size[i] = r300->velems->hw_format_size[i] / 4; vertex_size += size[i]; vbi = velem->vertex_buffer_index; @@ -610,6 +610,11 @@ static void r300_draw_range_elements(struct pipe_context* pipe, return; } + if (r300->incompatible_vb_layout || + r300->velems->incompatible_layout) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } @@ -704,6 +709,11 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, return; } + if (r300->incompatible_vb_layout || + r300->velems->incompatible_layout) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index cfec8ac2b7e..d19563c18ae 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1167,15 +1167,15 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, if (r300->screen->caps.has_tcl) { /* HW TCL. */ - /* Check if the stride is aligned to the size of DWORD. */ + r300->incompatible_vb_layout = FALSE; + + /* Check if the strides and offsets are aligned to the size of DWORD. */ for (i = 0; i < count; i++) { if (buffers[i].buffer) { - if (buffers[i].stride % 4 != 0) { - // XXX Shouldn't we align the buffer? - fprintf(stderr, "r300: set_vertex_buffers: " - "Unaligned buffer stride %i isn't supported.\n", - buffers[i].stride); - abort(); + if (buffers[i].stride % 4 != 0 || + buffers[i].buffer_offset % 4 != 0) { + r300->incompatible_vb_layout = TRUE; + break; } } } @@ -1248,7 +1248,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) * so PSC should just route stuff based on the vertex elements, * and not on attrib information. */ for (i = 0; i < velems->count; i++) { - format = velems->velem[i].src_format; + format = velems->hw_format[i]; type = r300_translate_vertex_data_type(format); if (type == R300_INVALID_FORMAT) { @@ -1280,12 +1280,15 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) vstream->count = (i >> 1) + 1; } +#define FORMAT_REPLACE(what, withwhat) \ + case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break + static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { struct r300_vertex_element_state *velems; - unsigned i, size; + unsigned i; enum pipe_format *format; assert(count <= PIPE_MAX_ATTRIBS); @@ -1293,88 +1296,69 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, if (velems != NULL) { velems->count = count; memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); + velems->incompatible_layout = FALSE; if (r300_screen(pipe->screen)->caps.has_tcl) { - r300_vertex_psc(velems); - - /* Check if the format is aligned to the size of DWORD. - * We only care about the blocksizes of the formats since - * swizzles are already set up. */ + /* Set the best hw format in case the original format is not + * supported by hw. */ for (i = 0; i < count; i++) { - format = &velems->velem[i].src_format; + velems->hw_format[i] = velems->velem[i].src_format; + format = &velems->hw_format[i]; - /* Replace some formats with their aligned counterparts, - * this is OK because we check for aligned strides too. */ + /* This is basically the list of unsupported formats. + * For now we don't care about the alignment, that's going to + * be sorted out after the PSC setup. */ switch (*format) { - /* Align to RGBA8. */ - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - *format = PIPE_FORMAT_R8G8B8A8_UNORM; - continue; - case PIPE_FORMAT_R8_SNORM: - case PIPE_FORMAT_R8G8_SNORM: - case PIPE_FORMAT_R8G8B8_SNORM: - *format = PIPE_FORMAT_R8G8B8A8_SNORM; - continue; - case PIPE_FORMAT_R8_USCALED: - case PIPE_FORMAT_R8G8_USCALED: - case PIPE_FORMAT_R8G8B8_USCALED: - *format = PIPE_FORMAT_R8G8B8A8_USCALED; - continue; - case PIPE_FORMAT_R8_SSCALED: - case PIPE_FORMAT_R8G8_SSCALED: - case PIPE_FORMAT_R8G8B8_SSCALED: - *format = PIPE_FORMAT_R8G8B8A8_SSCALED; - continue; - - /* Align to RG16. */ - case PIPE_FORMAT_R16_UNORM: - *format = PIPE_FORMAT_R16G16_UNORM; - continue; - case PIPE_FORMAT_R16_SNORM: - *format = PIPE_FORMAT_R16G16_SNORM; - continue; - case PIPE_FORMAT_R16_USCALED: - *format = PIPE_FORMAT_R16G16_USCALED; - continue; - case PIPE_FORMAT_R16_SSCALED: - *format = PIPE_FORMAT_R16G16_SSCALED; - continue; - case PIPE_FORMAT_R16_FLOAT: - *format = PIPE_FORMAT_R16G16_FLOAT; - continue; - - /* Align to RGBA16. */ - case PIPE_FORMAT_R16G16B16_UNORM: - *format = PIPE_FORMAT_R16G16B16A16_UNORM; - continue; - case PIPE_FORMAT_R16G16B16_SNORM: - *format = PIPE_FORMAT_R16G16B16A16_SNORM; - continue; - case PIPE_FORMAT_R16G16B16_USCALED: - *format = PIPE_FORMAT_R16G16B16A16_USCALED; - continue; - case PIPE_FORMAT_R16G16B16_SSCALED: - *format = PIPE_FORMAT_R16G16B16A16_SSCALED; - continue; - case PIPE_FORMAT_R16G16B16_FLOAT: - *format = PIPE_FORMAT_R16G16B16A16_FLOAT; - continue; + FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_UNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_USCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_SNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_FIXED, R32_FLOAT); + FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); default:; } - size = util_format_get_blocksize(*format); + velems->incompatible_layout = + velems->incompatible_layout || + velems->velem[i].src_format != velems->hw_format[i] || + velems->velem[i].src_offset % 4 != 0; + } - if (size % 4 != 0) { - /* XXX Shouldn't we align the format? */ - fprintf(stderr, "r300_create_vertex_elements_state: " - "Unaligned format %s:%i isn't supported\n", - util_format_short_name(*format), size); - assert(0); - abort(); - } + /* Now setup PSC. + * The unused components will be replaced by (..., 0, 1). */ + r300_vertex_psc(velems); + + /* Align the formats to the size of DWORD. + * We only care about the blocksizes of the formats since + * swizzles are already set up. */ + for (i = 0; i < count; i++) { + /* This is OK because we check for aligned strides too. */ + velems->hw_format_size[i] = + align(util_format_get_blocksize(velems->hw_format[i]), 4); } } } -- 2.30.2