st/nine: Explicit nine requirements
authorAxel Davy <axel.davy@ens.fr>
Sat, 3 Jan 2015 10:16:23 +0000 (11:16 +0100)
committerAxel Davy <axel.davy@ens.fr>
Thu, 5 Feb 2015 23:07:18 +0000 (00:07 +0100)
This patch raises nine requirements and disables nine for old
hw that don't match them.

Currently for these cards only games that don't have tight requirements
would work well with nine. However nine is missing several checks
regarding these limitations.
To make code and future patches less heavy, dropping support for these old
card seems a good solution.

That makes r500 the only dx9 generation cards supported by nine. It seems the one
with the less limitations for nine. Still not everything is ok, and we'll have
for example to implement shader recompilation for these cards to include
integer and boolean constants in the shader.
Eventually when this is done, we can reintroduce support for older cards.

Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Axel Davy <axel.davy@ens.fr>
src/gallium/state_trackers/nine/adapter9.c
src/gallium/state_trackers/nine/device9.c

index 481f86362f8f8546dc4e1fb56c50cd075b334653..bdf547e78c4bc37d87e2efdc1f5a79ff690ba1df 100644 (file)
@@ -39,6 +39,7 @@ NineAdapter9_ctor( struct NineAdapter9 *This,
                    struct NineUnknownParams *pParams,
                    struct d3dadapter9_context *pCTX )
 {
+    struct pipe_screen *hal = pCTX->hal;
     HRESULT hr = NineUnknown_ctor(&This->base, pParams);
     if (FAILED(hr)) { return hr; }
 
@@ -46,7 +47,7 @@ NineAdapter9_ctor( struct NineAdapter9 *This,
     nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier);
 
     This->ctx = pCTX;
-    if (!This->ctx->hal->get_param(This->ctx->hal, PIPE_CAP_CLIP_HALFZ)) {
+    if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) {
         ERR("Driver doesn't support d3d9 coordinates\n");
         return D3DERR_DRIVERINTERNALERROR;
     }
@@ -54,7 +55,44 @@ NineAdapter9_ctor( struct NineAdapter9 *This,
         !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) {
         ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n");
     }
-
+    /* Old cards had tricks to bypass some restrictions to implement
+     * everything and fit tight the requirements: number of constants,
+     * number of temp registers, special behaviours, etc. Since we don't
+     * have access to all this, we need a bit more than what dx9 required.
+     * For example we have to use more than 32 temp registers to emulate
+     * behaviours, while some dx9 hw don't have more. As for sm2 hardware,
+     * we could support vs2 / ps2 for them but it needs some more care, and
+     * as these are very old, we choose to drop support for them */
+
+    /* checks minimum requirements, most are vs3/ps3 strict requirements */
+    if (!hal->get_param(hal, PIPE_CAP_SM3) ||
+        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
+                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) ||
+        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
+                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) ||
+        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
+                              PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
+        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
+                              PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
+        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
+                              PIPE_SHADER_CAP_MAX_INPUTS) < 16 ||
+        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
+                              PIPE_SHADER_CAP_MAX_INPUTS) < 10) {
+        ERR("Your card is not supported by Gallium Nine. Minimum requirement "
+            "is >= r500, >= nv50, >= i965\n");
+        return D3DERR_DRIVERINTERNALERROR;
+    }
+    /* for r500 */
+    if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
+                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */
+        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
+                              PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */
+        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
+                              PIPE_SHADER_CAP_MAX_TEMPS) < 40 ||
+        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
+                              PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */
+        ERR("Your card is at the limit of Gallium Nine requirements. Some games "
+            "may run into issues because requirements are too tight\n");
     return D3D_OK;
 }
 
@@ -472,7 +510,6 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
                             D3DCAPS9 *pCaps )
 {
     struct pipe_screen *screen;
-    boolean sm3, vs;
     HRESULT hr;
 
     DBG("This=%p DeviceType=%s pCaps=%p\n", This,
@@ -492,10 +529,6 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
 #define D3DNPIPECAP(pcap, d3dcap) \
     (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))
 
-    sm3 = screen->get_param(screen, PIPE_CAP_SM3);
-    vs = !!(screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
-                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS));
-
     pCaps->DeviceType = DeviceType;
 
     pCaps->AdapterOrdinal = 0;
@@ -781,28 +814,16 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
     pCaps->MaxStreamStride = screen->get_param(screen,
             PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);
 
-    pCaps->VertexShaderVersion = sm3 ? D3DVS_VERSION(3,0) : D3DVS_VERSION(2,0);
-    if (vs) {
-        /* VS 2 as well as 3.0 supports a minimum of 256 consts, no matter how
-         * much our architecture moans about it. The problem is that D3D9
-         * expects access to 16 int consts (i#), containing 3 components and
-         * 16 booleans (b#), containing only 1 component. This should be packed
-         * into 20 float vectors (16 for i# and 16/4 for b#), since gallium has
-         * removed support for the loop counter/boolean files. */
-        pCaps->MaxVertexShaderConst =
-            _min((screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
-                     PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
-                     sizeof(float[4])) - 20,
-                NINE_MAX_CONST_F);
-        /* Fake the minimum cap for Windows. */
-        if (QUIRK(FAKE_CAPS)) {
-            pCaps->MaxVertexShaderConst = 256;
-        }
-    } else {
-        pCaps->MaxVertexShaderConst = 0;
-    }
+    pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
+
+    /* VS 2 as well as 3.0 supports a minimum of 256 consts.
+     * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them,
+     * advertise 256. Problem is with hw that can only do 256, because
+     * we need take a few slots for boolean and integer constants. For these
+     * we'll have to fail later if they use complex shaders. */
+    pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;
 
-    pCaps->PixelShaderVersion = sm3 ? D3DPS_VERSION(3,0) : D3DPS_VERSION(2,0);
+    pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
     pCaps->PixelShader1xMaxValue = 8.0f; /* XXX: wine */
 
     pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
@@ -919,23 +940,18 @@ NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
     else
         pCaps->VertexTextureFilterCaps = 0;
 
-    if (sm3) {
-        pCaps->MaxVertexShader30InstructionSlots =
-            screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
-                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
-        pCaps->MaxPixelShader30InstructionSlots =
-            screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
-                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
-        if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
-            pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
-        if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
-            pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
-        assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
-        assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
-    } else {
-        pCaps->MaxVertexShader30InstructionSlots = 0;
-        pCaps->MaxPixelShader30InstructionSlots = 0;
-    }
+    pCaps->MaxVertexShader30InstructionSlots =
+        screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
+                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
+    pCaps->MaxPixelShader30InstructionSlots =
+        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
+    if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
+        pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
+    if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
+        pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
+    assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
+    assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
 
     /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */
     pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);
index ef3d2b0be581f5412fc875237262b8eaabbdaea3..656f48860fd94e5fa29b3b3e9e5abdb47af0c9ad 100644 (file)
@@ -248,14 +248,15 @@ NineDevice9_ctor( struct NineDevice9 *This,
         struct pipe_resource tmpl;
         unsigned max_const_vs, max_const_ps;
 
+        /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
+         * we have to take in some more slots for int and bool*/
         max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,
                                 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
                                 sizeof(float[4]),
-                           NINE_MAX_CONST_ALL);
-        max_const_ps = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT,
-                                PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
-                                sizeof(float[4]),
                             NINE_MAX_CONST_ALL);
+        /* ps 3.0: 224 float constants. All cards supported support at least
+         * 256 constants for ps */
+        max_const_ps = 224 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
 
         This->max_vs_const_f = max_const_vs -
                                (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);