From: Michael Müller michael@fds-team.de
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d8/swapchain.c | 2 +- dlls/d3d9/device.c | 4 ++-- dlls/d3d9/swapchain.c | 2 +- dlls/dxgi/swapchain.c | 27 ++++++++++++++++++++++++--- dlls/wined3d/cs.c | 11 ++++++++++- dlls/wined3d/surface.c | 2 +- dlls/wined3d/swapchain.c | 5 +++-- dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 4 ++-- include/wine/wined3d.h | 2 +- 10 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/dlls/d3d8/swapchain.c b/dlls/d3d8/swapchain.c index 7003aa32dbcb..3a588b5e8c2b 100644 --- a/dlls/d3d8/swapchain.c +++ b/dlls/d3d8/swapchain.c @@ -105,7 +105,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_swapchain_Present(IDirect3DSwapChai
wined3d_mutex_lock(); hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0); + src_rect, dst_rect, dst_window_override, 0, 0); wined3d_mutex_unlock();
return hr; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index aac0961d559e..bc73699e5251 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -992,7 +992,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_Present(IDirect3DDevice9Ex * for (i = 0; i < device->implicit_swapchain_count; ++i) { if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, 0))) + src_rect, dst_rect, dst_window_override, 0, 0))) { wined3d_mutex_unlock(); return hr; @@ -3684,7 +3684,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_device_PresentEx(IDirect3DDevice9Ex for (i = 0; i < device->implicit_swapchain_count; ++i) { if (FAILED(hr = wined3d_swapchain_present(device->implicit_swapchains[i]->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, flags))) + src_rect, dst_rect, dst_window_override, 0, flags))) { wined3d_mutex_unlock(); return hr; diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c index 411040ad66df..dbb3f45b91d5 100644 --- a/dlls/d3d9/swapchain.c +++ b/dlls/d3d9/swapchain.c @@ -137,7 +137,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d9_swapchain_Present(IDirect3DSwapChai
wined3d_mutex_lock(); hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, - src_rect, dst_rect, dst_window_override, flags); + src_rect, dst_rect, dst_window_override, 0, flags); wined3d_mutex_unlock();
return hr; diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 1f88d71b77a7..7ddf51c0d5c9 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -528,11 +528,34 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_Present1(IDXGISwapChain1 *iface, UINT sync_interval, UINT flags, const DXGI_PRESENT_PARAMETERS *present_parameters) { struct dxgi_swapchain *swapchain = impl_from_IDXGISwapChain1(iface); + DWORD swap_interval; HRESULT hr;
TRACE("iface %p, sync_interval %u, flags %#x, present_parameters %p.\n", iface, sync_interval, flags, present_parameters);
+ switch (sync_interval) + { + case 0: + swap_interval = WINED3DPRESENT_INTERVAL_IMMEDIATE; + break; + case 1: + swap_interval = WINED3DPRESENT_INTERVAL_ONE; + break; + case 2: + swap_interval = WINED3DPRESENT_INTERVAL_TWO; + break; + case 3: + swap_interval = WINED3DPRESENT_INTERVAL_THREE; + break; + case 4: + swap_interval = WINED3DPRESENT_INTERVAL_FOUR; + break; + default: + WARN("Invalid sync interval %u.\n", sync_interval); + return DXGI_ERROR_INVALID_CALL; + } + if (flags & ~DXGI_PRESENT_TEST) FIXME("Unimplemented flags %#x.\n", flags); if (flags & DXGI_PRESENT_TEST) @@ -541,13 +564,11 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_Present1(IDXGISwapChain1 *iface, return S_OK; }
- if (sync_interval) - FIXME("Unimplemented sync interval %u.\n", sync_interval); if (present_parameters) FIXME("Ignored present parameters %p.\n", present_parameters);
wined3d_mutex_lock(); - hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, NULL, NULL, NULL, 0); + hr = wined3d_swapchain_present(swapchain->wined3d_swapchain, NULL, NULL, NULL, swap_interval, 0); wined3d_mutex_unlock();
return hr; diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 9f3ff4691d1a..d16a8997e931 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -94,6 +94,7 @@ struct wined3d_cs_present struct wined3d_swapchain *swapchain; RECT src_rect; RECT dst_rect; + DWORD swap_interval; DWORD flags; };
@@ -453,6 +454,12 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) swapchain = op->swapchain; wined3d_swapchain_set_window(swapchain, op->dst_window_override);
+ if (op->swap_interval && swapchain->desc.swap_interval != op->swap_interval) + { + swapchain->desc.swap_interval = op->swap_interval; + swapchain_update_swap_interval(swapchain); + } + swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags);
wined3d_resource_release(&swapchain->front_buffer->resource); @@ -465,7 +472,8 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) }
void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, - const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) + const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, + DWORD swap_interval, DWORD flags) { struct wined3d_cs_present *op; unsigned int i; @@ -477,6 +485,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw op->swapchain = swapchain; op->src_rect = *src_rect; op->dst_rect = *dst_rect; + op->swap_interval = swap_interval; op->flags = flags;
pending = InterlockedIncrement(&cs->pending_presents); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index ada71938da52..d7f5fcab7d52 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -4007,7 +4007,7 @@ HRESULT wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst /* Set the swap effect to COPY, we don't want the backbuffer to become * undefined. */ dst_swapchain->desc.swap_effect = WINED3D_SWAP_EFFECT_COPY; - wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0); + wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, 0, 0); dst_swapchain->desc.swap_effect = swap_effect;
return WINED3D_OK; diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 0d76b671717e..c7e9bf12d0b2 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -146,7 +146,8 @@ void CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWN }
HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, - const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) + const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, + DWORD swap_interval, DWORD flags) { RECT s, d;
@@ -177,7 +178,7 @@ HRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain, }
wined3d_cs_emit_present(swapchain->device->cs, swapchain, src_rect, - dst_rect, dst_window_override, flags); + dst_rect, dst_window_override, swap_interval, flags);
return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index d2b6bef36340..16d22f5263ac 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -281,7 +281,7 @@ @ cdecl wined3d_swapchain_get_desc(ptr ptr) @ cdecl wined3d_swapchain_get_raster_status(ptr ptr) @ cdecl wined3d_swapchain_incref(ptr) -@ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long) +@ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long long) @ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long) @ cdecl wined3d_swapchain_resize_target(ptr ptr) @ cdecl wined3d_swapchain_set_fullscreen(ptr ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f085f2d8b85e..bba80df35cfd 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3548,8 +3548,8 @@ void wined3d_cs_emit_draw_indirect(struct wined3d_cs *cs, GLenum primitive_type, void wined3d_cs_emit_flush(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_generate_mipmaps(struct wined3d_cs *cs, struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; void wined3d_cs_emit_preload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; -void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, - const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) DECLSPEC_HIDDEN; +void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, const RECT *src_rect, + const RECT *dst_rect, HWND dst_window_override, DWORD swap_interval, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) DECLSPEC_HIDDEN; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index b6a2ec38a004..96c1c25bf07c 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2656,7 +2656,7 @@ HRESULT __cdecl wined3d_swapchain_get_raster_status(const struct wined3d_swapcha struct wined3d_raster_status *raster_status); ULONG __cdecl wined3d_swapchain_incref(struct wined3d_swapchain *swapchain); HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, - const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags); + const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD swap_interval, DWORD flags); HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count, unsigned int width, unsigned int height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/dxgi/tests/device.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/dlls/dxgi/tests/device.c b/dlls/dxgi/tests/device.c index 8351a32e596d..d265978ba4b1 100644 --- a/dlls/dxgi/tests/device.c +++ b/dlls/dxgi/tests/device.c @@ -3353,6 +3353,63 @@ static void test_swapchain_parameters(void) DestroyWindow(window); }
+static void test_swapchain_present(void) +{ + DXGI_SWAP_CHAIN_DESC swapchain_desc; + IDXGISwapChain *swapchain; + IDXGIAdapter *adapter; + IDXGIFactory *factory; + IDXGIDevice *device; + unsigned int i; + ULONG refcount; + HRESULT hr; + + if (!(device = create_device(0))) + { + skip("Failed to create device.\n"); + return; + } + + hr = IDXGIDevice_GetAdapter(device, &adapter); + ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr); + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr); + IDXGIAdapter_Release(adapter); + + swapchain_desc.BufferDesc.Width = 800; + swapchain_desc.BufferDesc.Height = 600; + swapchain_desc.BufferDesc.RefreshRate.Numerator = 60; + swapchain_desc.BufferDesc.RefreshRate.Denominator = 60; + swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapchain_desc.SampleDesc.Count = 1; + swapchain_desc.SampleDesc.Quality = 0; + swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchain_desc.BufferCount = 1; + swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0); + swapchain_desc.Windowed = TRUE; + swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapchain_desc.Flags = 0; + + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain); + ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr); + + for (i = 0; i < 10; ++i) + { + hr = IDXGISwapChain_Present(swapchain, i, 0); + ok(hr == (i <= 4 ? S_OK : DXGI_ERROR_INVALID_CALL), + "Got unexpected hr %#x for sync interval %u.\n", hr, i); + } + hr = IDXGISwapChain_Present(swapchain, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + + IDXGISwapChain_Release(swapchain); + refcount = IDXGIDevice_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(swapchain_desc.OutputWindow); +} + static void test_maximum_frame_latency(void) { IDXGIDevice1 *device1; @@ -3654,6 +3711,7 @@ START_TEST(device) test_private_data(); test_swapchain_resize(); test_swapchain_parameters(); + test_swapchain_present(); test_maximum_frame_latency(); test_output_desc(); test_object_wrapping();
It does nothing when depth_stencil is NULL.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/context.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 32126b7dc078..4282cfb94d01 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2956,8 +2956,6 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - context_validate_onscreen_formats(context, NULL); - if (context->render_offscreen) { wined3d_texture_load(rt, context, FALSE);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
In Direct3D 10+, the render target at index 0 can be set to NULL.
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
Also, a more complex logic may be needed for acquiring context for no attachments draw calls.
There is a potential issue in the code: the assumption that the render target is a texture, but it is a bug in the current code.
--- dlls/wined3d/context.c | 53 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 4282cfb94d01..534f05a9f0bd 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -3157,6 +3157,7 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat { DWORD rt_mask = find_draw_buffers_mask(context, state); const struct wined3d_fb_state *fb = state->fb; + DWORD color_location = 0; DWORD *cur_mask;
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) @@ -3173,18 +3174,20 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat memset(context->blit_targets, 0, sizeof(context->blit_targets)); for (i = 0; i < context->gl_info->limits.buffers; ++i) { - if (fb->render_targets[i]) - { - context->blit_targets[i].gl_view = fb->render_targets[i]->gl_view; - context->blit_targets[i].resource = fb->render_targets[i]->resource; - context->blit_targets[i].sub_resource_idx = fb->render_targets[i]->sub_resource_idx; - context->blit_targets[i].layer_count = fb->render_targets[i]->layer_count; - } + if (!fb->render_targets[i]) + continue; + + context->blit_targets[i].gl_view = fb->render_targets[i]->gl_view; + context->blit_targets[i].resource = fb->render_targets[i]->resource; + context->blit_targets[i].sub_resource_idx = fb->render_targets[i]->sub_resource_idx; + context->blit_targets[i].layer_count = fb->render_targets[i]->layer_count; + + if (!color_location) + color_location = fb->render_targets[i]->resource->draw_binding; } context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, wined3d_rendertarget_view_get_surface(fb->depth_stencil), - fb->render_targets[0] ? fb->render_targets[0]->resource->draw_binding : 0, - fb->depth_stencil ? fb->depth_stencil->resource->draw_binding : 0); + color_location, fb->depth_stencil ? fb->depth_stencil->resource->draw_binding : 0); } }
@@ -4774,6 +4777,31 @@ static GLenum gl_tfb_primitive_type_from_d3d(enum wined3d_primitive_type primiti } }
+static struct wined3d_context *context_acquire_for_draw_call(const struct wined3d_device *device, + const struct wined3d_fb_state *fb) +{ + struct wined3d_texture *texture = NULL; + struct wined3d_rendertarget_view *rtv; + unsigned int sub_resource_idx = 0; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(fb->render_targets); ++i) + { + if ((rtv = fb->render_targets[i])) + break; + } + if (!rtv) + rtv = fb->depth_stencil; + + if (rtv) + { + texture = wined3d_texture_from_resource(rtv->resource); + sub_resource_idx = rtv->sub_resource_idx; + } + + return context_acquire(device, texture, sub_resource_idx); +} + /* Routine common to the draw primitive and draw indexed primitive routines */ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters) @@ -4792,12 +4820,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s if (!parameters->indirect && !parameters->u.direct.index_count) return;
- if (!(rtv = fb->render_targets[0])) - rtv = fb->depth_stencil; - if (rtv) - context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx); - else - context = context_acquire(device, NULL, 0); + context = context_acquire_for_draw_call(device, fb); if (!context->valid) { context_release(context);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 28 February 2018 at 16:26, Henri Verbeet hverbeet@codeweavers.com wrote:
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Actually, I did not necessarily mean to sign-off on this one just yet, although it could still happen.
On 28 February 2018 at 12:12, Józef Kucia jkucia@codeweavers.com wrote:
In Direct3D 10+, the render target at index 0 can be set to NULL.
Yes, but draw_primitive() at least seems to account for that. What is the issue there specifically?
@@ -4792,12 +4820,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s if (!parameters->indirect && !parameters->u.direct.index_count) return;
- if (!(rtv = fb->render_targets[0]))
rtv = fb->depth_stencil;
- if (rtv)
context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx);
- else
context = context_acquire(device, NULL, 0);
- context = context_acquire_for_draw_call(device, fb);
I.e., here.
On Wed, Feb 28, 2018 at 4:26 PM, Henri Verbeet hverbeet@gmail.com wrote:
On 28 February 2018 at 12:12, Józef Kucia jkucia@codeweavers.com wrote:
In Direct3D 10+, the render target at index 0 can be set to NULL.
Yes, but draw_primitive() at least seems to account for that. What is the issue there specifically?
The main problem is color_location set to 0 in context_state_fb().
@@ -4792,12 +4820,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s if (!parameters->indirect && !parameters->u.direct.index_count) return;
- if (!(rtv = fb->render_targets[0]))
rtv = fb->depth_stencil;
- if (rtv)
context = context_acquire(device, wined3d_texture_from_resource(rtv->resource), rtv->sub_resource_idx);
- else
context = context_acquire(device, NULL, 0);
- context = context_acquire_for_draw_call(device, fb);
I.e., here.
Yes, context_acquire_for_draw_call() should not be necessary. I'll send a v2. Thanks.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d11/tests/d3d11.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 5a36bc285956..f49efe7cd55a 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -7887,10 +7887,10 @@ static void test_sample_c_lz(void)
static void test_multiple_render_targets(void) { + ID3D11RenderTargetView *rtv[4], *tmp_rtv[4]; D3D11_TEXTURE2D_DESC texture_desc; ID3D11InputLayout *input_layout; unsigned int stride, offset, i; - ID3D11RenderTargetView *rtv[4]; ID3D11DeviceContext *context; ID3D11Texture2D *rt[4]; ID3D11VertexShader *vs; @@ -8025,9 +8025,21 @@ static void test_multiple_render_targets(void)
for (i = 0; i < ARRAY_SIZE(rtv); ++i) ID3D11DeviceContext_ClearRenderTargetView(context, rtv[i], red); - ID3D11DeviceContext_Draw(context, 4, 0); + check_texture_color(rt[0], 0xffffffff, 2); + check_texture_color(rt[1], 0x7f7f7f7f, 2); + check_texture_color(rt[2], 0x33333333, 2); + check_texture_color(rt[3], 0xff7f3300, 2);
+ for (i = 0; i < ARRAY_SIZE(rtv); ++i) + ID3D11DeviceContext_ClearRenderTargetView(context, rtv[i], red); + for (i = 0; i < ARRAY_SIZE(tmp_rtv); ++i) + { + memset(tmp_rtv, 0, sizeof(tmp_rtv)); + tmp_rtv[i] = rtv[i]; + ID3D11DeviceContext_OMSetRenderTargets(context, 4, tmp_rtv, NULL); + ID3D11DeviceContext_Draw(context, 4, 0); + } check_texture_color(rt[0], 0xffffffff, 2); check_texture_color(rt[1], 0x7f7f7f7f, 2); check_texture_color(rt[2], 0x33333333, 2);
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/context.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 534f05a9f0bd..6007c2b2556b 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -3128,7 +3128,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const { struct wined3d_rendertarget_view * const *rts = state->fb->render_targets; struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; - DWORD rt_mask, rt_mask_bits; + DWORD rt_mask, mask; unsigned int i;
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) @@ -3138,15 +3138,13 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const
rt_mask = ps ? ps->reg_maps.rt_mask : 1; rt_mask &= context->d3d_info->valid_rt_mask; - rt_mask_bits = rt_mask; - i = 0; - while (rt_mask_bits) + + mask = rt_mask; + while (mask) { - rt_mask_bits &= ~(1u << i); + i = wined3d_bit_scan(&mask); if (!rts[i] || rts[i]->format->id == WINED3DFMT_NULL) rt_mask &= ~(1u << i); - - i++; }
return rt_mask;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/d3d11/tests/d3d11.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index f49efe7cd55a..1826114c2c81 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -25032,6 +25032,93 @@ done: release_test_context(&test_context); }
+static void test_unbound_multisample_texture(void) +{ + struct d3d11_test_context test_context; + ID3D11DeviceContext *context; + ID3D11PixelShader *ps; + struct uvec4 cb_data; + ID3D11Device *device; + ID3D11Buffer *cb; + unsigned int i; + HRESULT hr; + + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + static const DWORD ps_code[] = + { +#if 0 + Texture2DMS<float4, 4> t; + + uint sample_index; + + float4 main(float4 position : SV_Position) : SV_Target + { + float3 p; + t.GetDimensions(p.x, p.y, p.z); + p *= float3(position.x / 640.0f, position.y / 480.0f, 0.0f); + /* sample index must be a literal */ + switch (sample_index) + { + case 1: return t.Load(int2(p.xy), 1); + case 2: return t.Load(int2(p.xy), 2); + case 3: return t.Load(int2(p.xy), 3); + default: return t.Load(int2(p.xy), 0); + } + } +#endif + 0x43425844, 0x03d62416, 0x1914ee8b, 0xccd08d68, 0x27f42136, 0x00000001, 0x000002f8, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000025c, 0x00000040, + 0x00000097, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x04042058, 0x00107000, 0x00000000, + 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, + 0x02000068, 0x00000002, 0x0700003d, 0x001000f2, 0x00000000, 0x00004001, 0x00000000, 0x00107e46, + 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00101046, 0x00000000, + 0x0a000038, 0x00100032, 0x00000000, 0x00100046, 0x00000000, 0x00004002, 0x3acccccd, 0x3b088889, + 0x00000000, 0x00000000, 0x0400004c, 0x0020800a, 0x00000000, 0x00000000, 0x03000006, 0x00004001, + 0x00000001, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, 0x08000036, 0x001000c2, + 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, + 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, 0x00000000, 0x00004001, 0x00000001, 0x0100003e, + 0x03000006, 0x00004001, 0x00000002, 0x0500001b, 0x00100032, 0x00000001, 0x00100046, 0x00000000, + 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, 0x00000000, 0x00004001, + 0x00000002, 0x0100003e, 0x03000006, 0x00004001, 0x00000003, 0x0500001b, 0x00100032, 0x00000001, + 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000001, 0x00107e46, + 0x00000000, 0x00004001, 0x00000003, 0x0100003e, 0x0100000a, 0x0500001b, 0x00100032, 0x00000000, + 0x00100046, 0x00000000, 0x08000036, 0x001000c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0900002e, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00107e46, + 0x00000000, 0x00004001, 0x00000000, 0x0100003e, 0x01000017, 0x0100003e, + }; + + if (!init_test_context(&test_context, NULL)) + return; + device = test_context.device; + context = test_context.immediate_context; + + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), NULL, &ps); + ok(hr == S_OK, "Failed to create pixel shader, hr %#x.\n", hr); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + + memset(&cb_data, 0, sizeof(cb_data)); + cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cb_data), &cb_data); + ID3D11DeviceContext_PSSetConstantBuffers(context, 0, 1, &cb); + + for (i = 0; i < 4; ++i) + { + cb_data.x = i; + ID3D11DeviceContext_UpdateSubresource(context, (ID3D11Resource *)cb, 0, NULL, &cb_data, 0, 0); + ID3D11DeviceContext_ClearRenderTargetView(context, test_context.backbuffer_rtv, white); + draw_quad(&test_context); + check_texture_color(test_context.backbuffer, 0x00000000, 1); + } + + ID3D11Buffer_Release(cb); + ID3D11PixelShader_Release(ps); + release_test_context(&test_context); +} + START_TEST(d3d11) { unsigned int argc, i; @@ -25161,4 +25248,5 @@ START_TEST(d3d11) test_combined_clip_and_cull_distances(); test_generate_mips(); test_alpha_to_coverage(); + test_unbound_multisample_texture(); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/wined3d/directx.c | 4 ++++ dlls/wined3d/wined3d_gl.h | 1 + 2 files changed, 5 insertions(+)
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index a1577c2aac3c..a95ded351dde 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -135,6 +135,7 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_fragment_layer_viewport", ARB_FRAGMENT_LAYER_VIEWPORT }, {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM }, {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER }, + {"GL_ARB_framebuffer_no_attachments", ARB_FRAMEBUFFER_NO_ATTACHMENTS}, {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT }, {"GL_ARB_framebuffer_sRGB", ARB_FRAMEBUFFER_SRGB }, {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4 }, @@ -2737,6 +2738,8 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glGetShaderPrecisionFormat) USE_GL_FUNC(glDepthRangef) USE_GL_FUNC(glClearDepthf) + /* GL_ARB_framebuffer_no_attachments */ + USE_GL_FUNC(glFramebufferParameteri) /* GL_ARB_framebuffer_object */ USE_GL_FUNC(glBindFramebuffer) USE_GL_FUNC(glBindRenderbuffer) @@ -3918,6 +3921,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, {ARB_DEBUG_OUTPUT, MAKEDWORD_VERSION(4, 3)}, {ARB_ES3_COMPATIBILITY, MAKEDWORD_VERSION(4, 3)}, {ARB_FRAGMENT_LAYER_VIEWPORT, MAKEDWORD_VERSION(4, 3)}, + {ARB_FRAMEBUFFER_NO_ATTACHMENTS, MAKEDWORD_VERSION(4, 3)}, {ARB_INTERNALFORMAT_QUERY2, MAKEDWORD_VERSION(4, 3)}, {ARB_SHADER_IMAGE_SIZE, MAKEDWORD_VERSION(4, 3)}, {ARB_SHADER_STORAGE_BUFFER_OBJECT, MAKEDWORD_VERSION(4, 3)}, diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index cc6f88802569..ed439e2a2ca3 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -68,6 +68,7 @@ enum wined3d_gl_extension ARB_FRAGMENT_LAYER_VIEWPORT, ARB_FRAGMENT_PROGRAM, ARB_FRAGMENT_SHADER, + ARB_FRAMEBUFFER_NO_ATTACHMENTS, ARB_FRAMEBUFFER_OBJECT, ARB_FRAMEBUFFER_SRGB, ARB_GEOMETRY_SHADER4,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
On 28 February 2018 at 12:12, Józef Kucia jkucia@codeweavers.com wrote:
@@ -105,7 +105,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH d3d8_swapchain_Present(IDirect3DSwapChai
wined3d_mutex_lock(); hr = wined3d_swapchain_present(swapchain->wined3d_swapchain,
src_rect, dst_rect, dst_window_override, 0);
src_rect, dst_rect, dst_window_override, 0, 0);
...
@@ -453,6 +454,12 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) swapchain = op->swapchain; wined3d_swapchain_set_window(swapchain, op->dst_window_override);
- if (op->swap_interval && swapchain->desc.swap_interval != op->swap_interval)
- {
swapchain->desc.swap_interval = op->swap_interval;
swapchain_update_swap_interval(swapchain);
- }
- swapchain->swapchain_ops->swapchain_present(swapchain, &op->src_rect, &op->dst_rect, op->flags);
It seems undesirable to have two conflicting mechanism to set the swap interval. Is there any reason to avoid using the DXGI mechanism for d3d9 and before as well?
@@ -528,11 +528,34 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_Present1(IDXGISwapChain1 *iface, UINT sync_interval, UINT flags, const DXGI_PRESENT_PARAMETERS *present_parameters) { struct dxgi_swapchain *swapchain = impl_from_IDXGISwapChain1(iface);
DWORD swap_interval; HRESULT hr;
TRACE("iface %p, sync_interval %u, flags %#x, present_parameters %p.\n", iface, sync_interval, flags, present_parameters);
switch (sync_interval)
{
case 0:
swap_interval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
break;
case 1:
swap_interval = WINED3DPRESENT_INTERVAL_ONE;
break;
case 2:
swap_interval = WINED3DPRESENT_INTERVAL_TWO;
break;
case 3:
swap_interval = WINED3DPRESENT_INTERVAL_THREE;
break;
case 4:
swap_interval = WINED3DPRESENT_INTERVAL_FOUR;
break;
default:
WARN("Invalid sync interval %u.\n", sync_interval);
return DXGI_ERROR_INVALID_CALL;
}
I think it would be better to just pass the DXGI interval to wined3d. Not in the least because we convert it back again in wined3d_swapchain_update_swap_interval_cs().
@@ -94,6 +94,7 @@ struct wined3d_cs_present struct wined3d_swapchain *swapchain; RECT src_rect; RECT dst_rect;
- DWORD swap_interval; DWORD flags;
};
unsigned int, probably.