st/nine: Implement RESZ hack

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>
This commit is contained in:
Axel Davy
2015-01-07 18:43:20 +01:00
parent 5c61f6344a
commit 42ac71a4e2
4 changed files with 65 additions and 0 deletions

View 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')

View 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;

View 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)) {

View 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;