Luca Barbieri
2009-Dec-30 17:14 UTC
[Nouveau] Add NOUVEAU_VTXIDX_IN_VRAM variable to put vertex/index buffers in VRAM
On some systems, putting vertex and index buffers in VRAM instead of
GART memory eliminates massive graphics corruption which is otherwise
present, due to unclear causes.
This patch adds an environment variable that does that, along with
helpful messages, prompting the user the report his configuration if we
got the default setting wrong.
It turns it on by default on NV49, as it is what I am seeing corruption
on.
This needs investigation and user reports to find out which cards are
susceptible.
---
src/gallium/drivers/nouveau/nouveau_screen.c | 57 +++++++++++++++++++++++--
src/gallium/drivers/nouveau/nouveau_screen.h | 2 +
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c
b/src/gallium/drivers/nouveau/nouveau_screen.c
index 0437af3..a30c9c6 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -47,11 +47,54 @@ nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct
nouveau_bo *bo,
return pb;
}
+static void
+nouveau_screen_bo_init(struct nouveau_screen* screen)
+{
+ screen->vertex_buffer_flags = 0;
+ screen->index_buffer_flags = 0;
+ if(screen->base.get_param(&screen->base, NOUVEAU_CAP_HW_VTXBUF) ||
screen->base.get_param(&screen->base, NOUVEAU_CAP_HW_IDXBUF))
+ {
+ int vram_hack_default = 0;
+ int vram_hack;
+ // TODO: add other cards that may need this hack.
+ // It may also depend on the specific card, CPU or AGP/PCIe chipset.
+ if(screen->device->chipset == 0x49)
+ vram_hack_default = 1;
+ vram_hack = debug_get_bool_option("NOUVEAU_VTXIDX_IN_VRAM",
vram_hack_default);
+
+ if(!vram_hack)
+ {
+ printf(
+ "Some systems may experience graphics corruption due to randomly
misplaced vertices.\n"
+ "If this is happening, export NOUVEAU_VTXIDX_IN_VRAM=1 may reduce or
eliminate the problem\n");
+ if(vram_hack == vram_hack_default)
+ printf("If it helps, please describe your hardware configuration and
software versions to nouveau at lists.freedesktop.org\n");
+ else
+ printf("If you are not experiencing any corruption in complex 3D
applications, please describe your hardware configuration and software versions
to nouveau at lists.freedesktop.org\n");
+ }
+ else
+ {
+ printf(
+ "A performance reducing hack is being used to help avoid graphics
corruption.\n"
+ "You can try export NOUVEAU_VTXIDX_IN_VRAM=0 to disable it.\n");
+ if(vram_hack == vram_hack_default)
+ printf("If it doesn't make things worse, please describe your
hardware configuration and software versions to nouveau at
lists.freedesktop.org\n");
+ }
+
+ if (screen->base.get_param(&screen->base, NOUVEAU_CAP_HW_VTXBUF))
+ screen->vertex_buffer_flags |= vram_hack ? NOUVEAU_BO_VRAM :
NOUVEAU_BO_GART;
+
+ if (screen->base.get_param(&screen->base, NOUVEAU_CAP_HW_IDXBUF))
+ screen->index_buffer_flags |= vram_hack ? NOUVEAU_BO_VRAM :
NOUVEAU_BO_GART;
+ }
+}
+
static struct pipe_buffer *
nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
unsigned usage, unsigned size)
{
- struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nouveau_screen* screen = nouveau_screen(pscreen);
+ struct nouveau_device *dev = screen->device;
struct nouveau_bo *bo = NULL;
uint32_t flags = NOUVEAU_BO_MAP;
int ret;
@@ -60,12 +103,14 @@ nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned
alignment,
flags |= NOUVEAU_BO_GART;
else
if (usage & PIPE_BUFFER_USAGE_VERTEX) {
- if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
- flags |= NOUVEAU_BO_GART;
+ if(screen->vertex_buffer_flags < 0)
+ nouveau_screen_bo_init(screen);
+ flags |= screen->vertex_buffer_flags;
} else
if (usage & PIPE_BUFFER_USAGE_INDEX) {
- if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
- flags |= NOUVEAU_BO_GART;
+ if(screen->index_buffer_flags < 0)
+ nouveau_screen_bo_init(screen);
+ flags |= screen->index_buffer_flags;
}
if (usage & PIPE_BUFFER_USAGE_PIXEL) {
@@ -233,6 +278,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct
nouveau_device *dev)
pscreen->fence_signalled = nouveau_screen_fence_signalled;
pscreen->fence_finish = nouveau_screen_fence_finish;
+ screen->vertex_buffer_flags = -1;
+ screen->index_buffer_flags = -1;
return 0;
}
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h
b/src/gallium/drivers/nouveau/nouveau_screen.h
index ebfc67a..ed32b35 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -5,6 +5,8 @@ struct nouveau_screen {
struct pipe_screen base;
struct nouveau_device *device;
struct nouveau_channel *channel;
+ int vertex_buffer_flags;
+ int index_buffer_flags;
};
static inline struct nouveau_screen *
--
1.6.3.3
Seemingly Similar Threads
- [mesa v2 5/9] nouveau: fix screen creation failure paths
- [mesa v2 5/9] nouveau: fix screen creation failure paths
- [mesa v2 5/9] nouveau: fix screen creation failure paths
- [Bug 27603] New: Celestia 1.6.0 crashes with nv04_surface_copy_swizzle assertion
- Help with controllers specs
