From 270dbe01ea6b36c38f8cf2bc6a66449caa719a01 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Thu, 17 Apr 2025 22:22:19 -0700 Subject: [PATCH] nv2a: Increase MAX_BATCH_LENGTH beyond highest known retail use --- hw/xbox/nv2a/nv2a_regs.h | 13 ++++++++++++- hw/xbox/nv2a/pgraph/pgraph.c | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 0c0fb70eef..2bdac1d93f 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -1467,7 +1467,18 @@ #define NV2A_NUM_SUBCHANNELS 8 #define NV2A_CACHE1_SIZE 128 -#define NV2A_MAX_BATCH_LENGTH 0x1FFFF +/* This is a multi-use limit. Testing on an Xbox 1.0, it is possible to send + * arrays of at least 0x0FFFFF elements without issue, however sending + * NV097_DRAW_ARRAYS with a start value > 0xFFFF raises an exception implying + * that there may be a vertex limit. Since xemu uses batch length for vertex + * elements in NV097_INLINE_ARRAY the size should ideally be high enough to + * accommodate 0xFFFF vertices with maximum attributes specified. + * + * Retail games are known to send at least 0x410FA elements in a single draw, so + * a somewhat larger value is selected to balance memory use with real-world + * limits. + */ +#define NV2A_MAX_BATCH_LENGTH 0x07FFFF #define NV2A_VERTEXSHADER_ATTRIBUTES 16 #define NV2A_MAX_TEXTURES 4 diff --git a/hw/xbox/nv2a/pgraph/pgraph.c b/hw/xbox/nv2a/pgraph/pgraph.c index feb5f858ca..fc6420fff0 100644 --- a/hw/xbox/nv2a/pgraph/pgraph.c +++ b/hw/xbox/nv2a/pgraph/pgraph.c @@ -2692,7 +2692,11 @@ DEF_METHOD(NV097, DRAW_ARRAYS) int32_t count = GET_MASK(parameter, NV097_DRAW_ARRAYS_COUNT) + 1; if (pg->inline_elements_length) { - /* FIXME: Determine HW behavior for overflow case. */ + /* FIXME: HW throws an exception if the start index is > 0xFFFF. This + * would prevent this assert from firing for any reasonable choice of + * NV2A_MAX_BATCH_LENGTH (which must be larger to accommodate + * NV097_INLINE_ARRAY anyway) + */ assert((pg->inline_elements_length + count) < NV2A_MAX_BATCH_LENGTH); assert(!pg->draw_arrays_prevent_connect);