[PATCH v4 2/3] wined3d: Issue texture barrier before using a texture attached to FBO.
Paul Gofman
gofmanp at gmail.com
Wed Oct 23 11:44:58 CDT 2019
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45978
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v4:
- use wait_query function.
dlls/d3d9/tests/visual.c | 163 ++++++++++++++++++++++++++++++++-
dlls/wined3d/adapter_gl.c | 7 ++
dlls/wined3d/context.c | 29 ++++++
dlls/wined3d/wined3d_gl.h | 2 +
dlls/wined3d/wined3d_private.h | 23 ++++-
5 files changed, 222 insertions(+), 2 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index e7076aeed6..ebec6dc27d 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -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();
}
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index ed1022030b..e83aebfa56 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -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)},
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 9cd6a6e3de..e9750c41c5 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -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)
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 678ad1a4ef..3372b4b6be 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -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,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 307f7a42ad..88833aef70 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -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"
--
2.21.0
More information about the wine-devel
mailing list