<div dir="ltr"><div><br></div><div>Hi,</div><div><br></div><div>I made an attempt to run Enemy Territories Quake Wars using the OpenSWR driver and I found a number of bugs in the implementation</div><div><br></div><div>The final result of the 'hacks' below is the first one or two frames of the actual game rendering but with most of the rendered textures painted in red (perhaps related with the miss definition of LATC2 as BC5?).  After that Mesa triggers a GL_OUT_OF_MEMORY on glCompressedTexSubImage2D (perhaps another variant of DXTn that I should map).</div><div><br></div><div>As I'm new and I'm not sure how to proceed I will just report them.</div><div><br></div><div>1) INT64 not defined for 32-bit build of Mesa3D (ETQW is a 32-bit binary), I used uint64_t instead.</div><div><br></div><div><div>diff --git a/src/gallium/drivers/swr/rasterizer/core/utils.h b/src/gallium/drivers/swr/rasterizer/core/utils.h</div><div>index 79f45eb..039db2c 100644</div><div>--- a/src/gallium/drivers/swr/rasterizer/core/utils.h</div><div>+++ b/src/gallium/drivers/swr/rasterizer/core/utils.h</div><div>@@ -37,7 +37,7 @@</div><div> #define _MM_INSERT_EPI64 _mm_insert_epi64</div><div> #define _MM_EXTRACT_EPI64 _mm_extract_epi64</div><div> #else</div><div>-INLINE INT64 _MM_EXTRACT_EPI64(__m128i a, const int32_t ndx)</div><div>+INLINE uint64_t _MM_EXTRACT_EPI64(__m128i a, const int32_t ndx)</div><div> {</div><div>     OSALIGNLINE(uint32_t) elems[4];</div><div>     _mm_store_si128((__m128i*)elems, a);</div><div>@@ -55,7 +55,7 @@ INLINE INT64 _MM_EXTRACT_EPI64(__m128i a, const int32_t ndx)</div><div>     }</div><div> }</div><div><br></div><div>-INLINE __m128i  _MM_INSERT_EPI64(__m128i a, INT64 b, const int32_t ndx)</div><div>+INLINE __m128i  _MM_INSERT_EPI64(__m128i a, uint64_t b, const int32_t ndx)</div><div> {</div><div>     OSALIGNLINE(int64_t) elems[2];</div><div>     _mm_store_si128((__m128i*)elems, a);</div></div><div><br></div><div>2) total_size is defined just as 'unsigned' and in a 32-bit build that's a 32-bit value which is smaller than the largest texture size defined, so it should be defined as 64-bit value. Not sure if the 1048 values in the definition of SWR_MAX_TEXTURE_SIZE are intended or not (or an error changing from 2048 x 2048)-</div><div><br></div><div>3) the DXTn texture formats are not properly mapped to the internal formats (BCn_UNORM).  Ignore LATC2 below as that is just a hack to get something running, from what I remember BC5 doesn't matches LATC2 definition.  The lack of support for DXTn formats triggers GL_OUT_OF_MEMORY errors before the actual game starts.  Note that I'm running a Virtual Box Ubuntu VM with 8 GBs of RAM so perhaps these GL_OUT_OF_MEMORY are masking another kind of error on the texture format conversion logic.</div><div><br></div><div><div>diff --git a/src/gallium/drivers/swr/swr_screen.cpp b/src/gallium/drivers/swr/swr_screen.cpp</div><div>index 3790fea..60e289f 100644</div><div>--- a/src/gallium/drivers/swr/swr_screen.cpp</div><div>+++ b/src/gallium/drivers/swr/swr_screen.cpp</div><div>@@ -55,7 +55,7 @@ extern "C" {</div><div>  * Max texture sizes</div><div>  * XXX Check max texture size values against core and sampler.</div><div>  */</div><div>-#define SWR_MAX_TEXTURE_SIZE (4 * 1048 * 1048 * 1024ULL) /* 4GB */</div><div>+#define SWR_MAX_TEXTURE_SIZE (4 * 1024 * 1024 * 1024ULL) /* 4GB */</div><div> #define SWR_MAX_TEXTURE_2D_LEVELS 14  /* 8K x 8K for now */</div><div> #define SWR_MAX_TEXTURE_3D_LEVELS 12  /* 2K x 2K x 2K for now */</div><div> #define SWR_MAX_TEXTURE_CUBE_LEVELS 14  /* 8K x 8K for now */</div><div>@@ -447,6 +447,12 @@ mesa_to_swr_format(enum pipe_format format)</div><div>       return R32_FLOAT_X8X24_TYPELESS;</div><div>    case PIPE_FORMAT_L8A8_UNORM:</div><div>       return R8G8_UNORM;</div><div>+   case PIPE_FORMAT_DXT1_RGB:</div><div>+      return BC1_UNORM;</div><div>+   case PIPE_FORMAT_DXT5_RGBA:</div><div>+      return BC3_UNORM;</div><div>+   case PIPE_FORMAT_LATC2_UNORM:</div><div>+     return BC5_UNORM;</div><div>    default:</div><div>       break;</div><div>    }</div><div>@@ -514,11 +520,11 @@ swr_texture_layout(struct swr_screen *screen,</div><div><br></div><div>    SWR_FORMAT_INFO finfo = GetFormatInfo(res->swr.format);</div><div><br></div><div>-   unsigned total_size = 0;</div><div>-   unsigned width = pt->width0;</div><div>-   unsigned height = pt->height0;</div><div>-   unsigned depth = pt->depth0;</div><div>-   unsigned layers = pt->array_size;</div><div>+   unsigned long long total_size = 0;</div><div>+   unsigned int width = pt->width0;</div><div>+   unsigned int height = pt->height0;</div><div>+   unsigned int depth = pt->depth0;</div><div>+   unsigned int layers = pt->array_size;</div><div><br></div><div>    for (int level = 0; level <= pt->last_level; level++) {</div><div>       unsigned alignedWidth, alignedHeight;</div></div><div><br></div><div>4) An error in the interaction between the Gallium Blitter (source seems to be a texture, a few previous blit operations worked) and OpenSWR handling of vertex buffers.  That's a bit more difficult to explain ...  It seems swr has some expectation on the state of the vertex buffers defined in ctx->vertex_buffers that the Blitter, or the functions used by the Blitter, are not fulfilling.  From what I understand the Blitter sets the state to a single vertex buffer, but swr_update_derived() finds ctx->num_vertex_buffers set to 4, probably because previous draw calls use 4 vertex buffers.  My guess is that when combining the current vertex buffer state with the new one in util_set_vertex_buffers_count() (src/gallium/auxiliary/util/u_helpers.c) the old 4 vertex buffers 'survive' and only the new one defined by the Blitter is updated.  The swr driver may expect these old vertex buffers to be 'disabled' previously.  When swr_update_derived() is called the incorrectly active vertex buffers don't have pitch/stream_pitch defined, the size becomes 0 and swr_copy_to_scratch_space() triggers an assert on size.  The code below is just a hack to make it work, I suppose the correct solution is in a different place related with the assumptions the swr driver makes on the state of the vertex buffers.</div><div><br></div><div><div>diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp</div><div>index de41ddc..70ebb16 100644</div><div>--- a/src/gallium/drivers/swr/swr_state.cpp</div><div>+++ b/src/gallium/drivers/swr/swr_state.cpp</div><div>@@ -1018,13 +1020,18 @@ swr_update_derived(struct pipe_context *pipe,<br></div><div>             max_vertex = info.max_index + 1;</div><div>             partial_inbounds = 0;</div><div><br></div><div>-            /* Copy only needed vertices to scratch space */</div><div>-            size = AlignUp(size, 4);</div><div>-            const void *ptr = (const uint8_t *) vb->user_buffer</div><div>-               + info.min_index * pitch;</div><div>-            ptr = swr_copy_to_scratch_space(</div><div>-               ctx, &ctx->scratch->vertex_buffer, ptr, size);</div><div>-            p_data = (const uint8_t *)ptr - info.min_index * pitch;</div><div>+            if (size > 0)</div><div>+            {</div><div>+               /* Copy only needed vertices to scratch space */</div><div>+               size = AlignUp(size, 4);</div><div>+               const void *ptr = (const uint8_t *) vb->user_buffer</div><div>+                  + info.min_index * pitch;</div><div>+               ptr = swr_copy_to_scratch_space(</div><div>+                  ctx, &ctx->scratch->vertex_buffer, ptr, size);</div><div>+               p_data = (const uint8_t *)ptr - info.min_index * pitch;</div><div>+            }</div><div>+            else</div><div>+               p_data = NULL;</div><div>          }</div><div><br></div><div>          swrVertexBuffers[i] = {0};</div></div><div><br></div><div>Victor<br></div></div>