st/nine: Implement RESZ hack
authorAxel Davy <axel.davy@ens.fr>
Wed, 7 Jan 2015 17:43:20 +0000 (18:43 +0100)
committerAxel Davy <axel.davy@ens.fr>
Thu, 5 Feb 2015 23:07:18 +0000 (00:07 +0100)
This D3D hack allows to resolve a multisampled
depth buffer into a single sampled one.

Note that the implementation is slightly incorrect.
When querying the content of D3DRS_POINTSIZE,
it should return the resz code if it has been set.
This behaviour will be implemented when state changes
will be reworked. For now the current behaviour is ok,
since apps use the D3DCREATE_PUREDEVICE flag when creating
the device, which means they won't read states and in exchange
get better performance.

Reviewed-by: Tiziano Bacocco <tizbac2@gmail.com>
Signed-off-by: Axel Davy <axel.davy@ens.fr>
include/D3D9/d3d9types.h
src/gallium/state_trackers/nine/adapter9.c
src/gallium/state_trackers/nine/device9.c
src/gallium/state_trackers/nine/nine_pipe.h

index 456ae9ffb02d56589b9c0e01d5f6d54ba86659b2..859c2f56dc4540d273cd3accef22e6f2a3ecef5d 100644 (file)
@@ -658,6 +658,7 @@ typedef enum _D3DFORMAT {
     D3DFMT_NVDB = MAKEFOURCC('N', 'V', 'D', 'B'),
     D3DFMT_NV11 = MAKEFOURCC('N', 'V', '1', '1'),
     D3DFMT_NV12 = MAKEFOURCC('N', 'V', '1', '2'),
+    D3DFMT_RESZ = MAKEFOURCC('R', 'E', 'S', 'Z'),
     D3DFMT_Y210 = MAKEFOURCC('Y', '2', '1', '0'),
     D3DFMT_Y216 = MAKEFOURCC('Y', '2', '1', '6'),
     D3DFMT_Y410 = MAKEFOURCC('Y', '4', '1', '0')
index bdf547e78c4bc37d87e2efdc1f5a79ff690ba1df..6ff197e1dfe8c716a5cfe824a99c788c3f9f455d 100644 (file)
@@ -305,6 +305,12 @@ NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
          RType == D3DRTYPE_TEXTURE))
         return D3D_OK;
 
+    /* RESZ hack */
+    if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&
+        RType == D3DRTYPE_SURFACE)
+        return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?
+               D3D_OK : D3DERR_NOTAVAILABLE;
+
     if (Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
         bind |= PIPE_BIND_BLENDABLE;
 
index b7e83a4bab9e062954d4961512c80dadbdc01d8d..0326442f9492c831dbf0081fb49bed758a372276 100644 (file)
@@ -1991,6 +1991,60 @@ NineDevice9_GetClipPlane( struct NineDevice9 *This,
     return D3D_OK;
 }
 
+#define RESZ_CODE 0x7fa05000
+
+static HRESULT
+NineDevice9_ResolveZ( struct NineDevice9 *This )
+{
+    struct nine_state *state = &This->state;
+    const struct util_format_description *desc;
+    struct NineSurface9 *source = state->ds;
+    struct NineBaseTexture9 *destination = state->texture[0];
+    struct pipe_resource *src, *dst;
+    struct pipe_blit_info blit;
+
+    DBG("RESZ resolve\n");
+
+    user_assert(source && destination &&
+                destination->base.type == D3DRTYPE_TEXTURE, D3DERR_INVALIDCALL);
+
+    src = source->base.resource;
+    dst = destination->base.resource;
+
+    user_assert(src && dst, D3DERR_INVALIDCALL);
+
+    /* check dst is depth format. we know already for src */
+    desc = util_format_description(dst->format);
+    user_assert(desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS, D3DERR_INVALIDCALL);
+
+    blit.src.resource = src;
+    blit.src.level = 0;
+    blit.src.format = src->format;
+    blit.src.box.z = 0;
+    blit.src.box.depth = 1;
+    blit.src.box.x = 0;
+    blit.src.box.y = 0;
+    blit.src.box.width = src->width0;
+    blit.src.box.height = src->height0;
+
+    blit.dst.resource = dst;
+    blit.dst.level = 0;
+    blit.dst.format = dst->format;
+    blit.dst.box.z = 0;
+    blit.dst.box.depth = 1;
+    blit.dst.box.x = 0;
+    blit.dst.box.y = 0;
+    blit.dst.box.width = dst->width0;
+    blit.dst.box.height = dst->height0;
+
+    blit.mask = PIPE_MASK_ZS;
+    blit.filter = PIPE_TEX_FILTER_NEAREST;
+    blit.scissor_enable = FALSE;
+
+    This->pipe->blit(This->pipe, &blit);
+    return D3D_OK;
+}
+
 HRESULT WINAPI
 NineDevice9_SetRenderState( struct NineDevice9 *This,
                             D3DRENDERSTATETYPE State,
@@ -2001,6 +2055,9 @@ NineDevice9_SetRenderState( struct NineDevice9 *This,
     DBG("This=%p State=%u(%s) Value=%08x\n", This,
         State, nine_d3drs_to_string(State), Value);
 
+    if (State == D3DRS_POINTSIZE && Value == RESZ_CODE)
+        return NineDevice9_ResolveZ(This);
+
     user_assert(State < Elements(state->rs), D3DERR_INVALIDCALL);
 
     if (likely(state->rs[State] != Value) || unlikely(This->is_recording)) {
index 41792f09e8ce0e207c6975d7b1b480a638d145e3..4fb6fa38ba4d3d34568645bc3d3c09f810fbcf16 100644 (file)
@@ -284,6 +284,7 @@ d3dformat_to_string(D3DFORMAT fmt)
     case D3DFMT_DF24: return "D3DFMT_DF24";
     case D3DFMT_INTZ: return "D3DFMT_INTZ";
     case D3DFMT_NVDB: return "D3DFMT_NVDB";
+    case D3DFMT_RESZ: return "D3DFMT_RESZ";
     case D3DFMT_NULL: return "D3DFMT_NULL";
     default:
         break;