wined3d: Issue texture barrier before using a texture attached to FBO.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45978
Signed-off-by: Paul Gofman <gofmanp@gmail.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2019-10-23 19:44:58 +03:00 committed by Alexandre Julliard
parent b9d0cec5f2
commit a5551040f2
5 changed files with 222 additions and 2 deletions

View file

@ -33,7 +33,7 @@
#define COBJMACROS
#include <d3d9.h>
#include "wine/test.h"
#include "utils.h"
#include "wine/heap.h"
struct vec2
@ -26263,6 +26263,166 @@ static void test_draw_mapped_buffer(void)
DestroyWindow(window);
}
static void test_sample_attached_rendertarget(void)
{
D3DADAPTER_IDENTIFIER9 identifier;
IDirect3DQuery9 *event_query;
IDirect3DTexture9 *texture;
IDirect3DVertexBuffer9 *vb;
IDirect3DPixelShader9 *ps;
IDirect3DDevice9 *device;
IDirect3DSurface9 *rt;
IDirect3D9 *d3d;
unsigned int i;
ULONG refcount;
D3DCOLOR color;
BOOL is_warp;
HWND window;
HRESULT hr;
void *data;
static const struct
{
struct vec3 posistion;
struct vec2 texcoord;
}
quad[] =
{
{{-1.0f, -1.0f, 0.1f}, {0.0f, 0.0f}},
{{-1.0f, 1.0f, 0.1f}, {0.0f, 1.0f}},
{{ 1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}},
{{ 1.0f, 1.0f, 0.1f}, {1.0f, 1.0f}},
};
static const DWORD pixel_shader_code[] =
{
0xffff0200, /* ps_2_0 */
0x05000051, 0xa00f0000, 0x3e800000, 0x3e800000, 0x3e800000, 0x3e800000,
/* def c0, 0.25, 0.25, 0.25, 0.25 */
0x0200001f, 0x80000000, 0xb00f0000, /* dcl t0 */
0x0200001f, 0x90000000, 0xa00f0800, /* dcl_2d s0 */
0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
0x03000002, 0x800f0000, 0x80e40000, 0xa0e40000, /* add r0, r0, c0 */
0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
0x0000ffff
};
window = create_window();
ok(!!window, "Failed to create a window.\n");
d3d = Direct3DCreate9(D3D_SDK_VERSION);
ok(!!d3d, "Failed to create a D3D object.\n");
hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
is_warp = adapter_is_warp(&identifier);
if (!(device = create_device(d3d, window, window, TRUE)))
{
skip("Failed to create a D3D device, skipping tests.\n");
IDirect3D9_Release(d3d);
DestroyWindow(window);
return;
}
hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, NULL);
if (hr == D3DERR_NOTAVAILABLE)
{
/* Without synchronization native d3d seems to show race condition on
* render target update, similar to opengl without using texture barrier. */
skip("Event queries are not supported, skipping test.\n");
IDirect3DDevice9_Release(device);
IDirect3D9_Release(d3d);
DestroyWindow(window);
return;
}
hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &event_query);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DQuery9_Issue(event_query, D3DISSUE_END);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), D3DUSAGE_DYNAMIC,
D3DFVF_XYZ | D3DFVF_TEX1, D3DPOOL_DEFAULT, &vb, NULL);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), &data, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
memcpy(data, quad, sizeof(quad));
hr = IDirect3DVertexBuffer9_Unlock(vb);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &rt);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x01010101, 0.0, 0);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
check_rt_color(rt, 0x00010101);
hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &ps);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_BeginScene(device);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_SetPixelShader(device, ps);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < 3; ++i)
{
wait_query(event_query);
hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DQuery9_Issue(event_query, D3DISSUE_END);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
}
hr = IDirect3DDevice9_EndScene(device);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
color = getPixelColor(device, 0, 0);
if (is_warp || color == 0x00010101)
skip("Sampling attached render targets is not supported.\n");
else
check_rt_color(rt, 0x00c1c1c1);
IDirect3DQuery9_Release(event_query);
IDirect3DVertexBuffer9_Release(vb);
IDirect3DPixelShader9_Release(ps);
IDirect3DSurface9_Release(rt);
IDirect3DTexture9_Release(texture);
refcount = IDirect3DDevice9_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D9_Release(d3d);
DestroyWindow(window);
}
START_TEST(visual)
{
@ -26409,4 +26569,5 @@ START_TEST(visual)
test_desktop_window();
test_mismatched_sample_types();
test_draw_mapped_buffer();
test_sample_attached_rendertarget();
}

View file

@ -159,6 +159,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
{"GL_ARB_vertex_shader", ARB_VERTEX_SHADER },
{"GL_ARB_vertex_type_2_10_10_10_rev", ARB_VERTEX_TYPE_2_10_10_10_REV},
{"GL_ARB_viewport_array", ARB_VIEWPORT_ARRAY },
{"GL_ARB_texture_barrier", ARB_TEXTURE_BARRIER },
/* ATI */
{"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER },
@ -228,6 +229,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
{"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2 },
{"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION },
{"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3 },
{"GL_NV_texture_barrier", NV_TEXTURE_BARRIER },
};
static const struct wined3d_extension_map wgl_extension_map[] =
@ -2454,6 +2456,8 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
USE_GL_FUNC(glViewportArrayv)
USE_GL_FUNC(glViewportIndexedf)
USE_GL_FUNC(glViewportIndexedfv)
/* GL_ARB_texture_barrier */
USE_GL_FUNC(glTextureBarrier);
/* GL_ATI_fragment_shader */
USE_GL_FUNC(glAlphaFragmentOp1ATI)
USE_GL_FUNC(glAlphaFragmentOp2ATI)
@ -2644,6 +2648,8 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
USE_GL_FUNC(glCombinerParameteriNV)
USE_GL_FUNC(glCombinerParameterivNV)
USE_GL_FUNC(glFinalCombinerInputNV)
/* GL_NV_texture_barrier */
USE_GL_FUNC(glTextureBarrierNV);
/* WGL extensions */
USE_GL_FUNC(wglChoosePixelFormatARB)
USE_GL_FUNC(wglGetExtensionsStringARB)
@ -3406,6 +3412,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
{ARB_CULL_DISTANCE, MAKEDWORD_VERSION(4, 5)},
{ARB_DERIVATIVE_CONTROL, MAKEDWORD_VERSION(4, 5)},
{ARB_SHADER_TEXTURE_IMAGE_SAMPLES, MAKEDWORD_VERSION(4, 5)},
{ARB_TEXTURE_BARRIER, MAKEDWORD_VERSION(4, 5)},
{ARB_PIPELINE_STATISTICS_QUERY, MAKEDWORD_VERSION(4, 6)},
{ARB_POLYGON_OFFSET_CLAMP, MAKEDWORD_VERSION(4, 6)},

View file

@ -3696,6 +3696,9 @@ static void context_preload_texture(struct wined3d_context *context,
if (!(texture = state->textures[idx]))
return;
if (wined3d_resource_check_fbo_attached(state, &texture->resource))
context->uses_fbo_attached_resources = 1;
wined3d_texture_load(texture, context, is_srgb_enabled(state->sampler_states[idx]));
}
@ -3929,6 +3932,8 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
unsigned int i, base;
WORD map;
context->uses_fbo_attached_resources = 0;
if (!have_framebuffer_attachment(gl_info->limits.buffers, fb->render_targets, fb->depth_stencil))
{
if (!gl_info->supported[ARB_FRAMEBUFFER_NO_ATTACHMENTS])
@ -4984,6 +4989,30 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
checkGLcall("glPatchParameteri");
}
if (context->uses_fbo_attached_resources)
{
static unsigned int fixme_once;
if (gl_info->supported[ARB_TEXTURE_BARRIER])
{
GL_EXTCALL(glTextureBarrier());
}
else if (gl_info->supported[NV_TEXTURE_BARRIER])
{
GL_EXTCALL(glTextureBarrierNV());
}
else
{
if (!fixme_once++)
FIXME("Sampling attached render targets is not supported.\n");
WARN("Sampling attached render targets is not supported, skipping draw.\n");
context_release(context);
return;
}
checkGLcall("glTextureBarrier");
}
if (parameters->indirect)
{
if (!context->use_immediate_mode_draw && !emulation)

View file

@ -142,6 +142,7 @@ enum wined3d_gl_extension
ARB_VERTEX_SHADER,
ARB_VERTEX_TYPE_2_10_10_10_REV,
ARB_VIEWPORT_ARRAY,
ARB_TEXTURE_BARRIER,
/* ATI */
ATI_FRAGMENT_SHADER,
ATI_SEPARATE_STENCIL,
@ -204,6 +205,7 @@ enum wined3d_gl_extension
NV_VERTEX_PROGRAM2,
NV_VERTEX_PROGRAM2_OPTION,
NV_VERTEX_PROGRAM3,
NV_TEXTURE_BARRIER,
/* WGL extensions */
WGL_ARB_PIXEL_FORMAT,
WGL_EXT_SWAP_CONTROL,

View file

@ -1961,6 +1961,7 @@ struct wined3d_context
DWORD use_immediate_mode_draw : 1;
DWORD uses_uavs : 1;
DWORD uses_fbo_attached_resources : 1;
DWORD transform_feedback_active : 1;
DWORD transform_feedback_paused : 1;
DWORD fog_coord : 1;
@ -1969,7 +1970,7 @@ struct wined3d_context
DWORD destroyed : 1;
DWORD destroy_delayed : 1;
DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */
DWORD padding : 15;
DWORD padding : 14;
DWORD constant_update_mask;
DWORD numbered_array_mask;
@ -5279,6 +5280,26 @@ static inline void wined3d_context_copy_bo_address(struct wined3d_context *conte
dst, dst_bind_flags, src, src_bind_flags, size);
}
static inline BOOL wined3d_resource_check_fbo_attached(const struct wined3d_state *state,
const struct wined3d_resource *resource)
{
struct wined3d_rendertarget_view * const *rts = &state->fb->render_targets[0];
unsigned int i;
if ((resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)
&& state->fb->depth_stencil && state->fb->depth_stencil->resource == resource)
return TRUE;
if (!(resource->bind_flags & WINED3D_BIND_RENDER_TARGET))
return FALSE;
for (i = 0; i < MAX_RENDER_TARGET_VIEWS; ++i)
if (rts[i] && rts[i]->resource == resource)
return TRUE;
return FALSE;
}
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"