[PATCH 7/8] d3d12/tests: Use multiple command lists in test_swapchain_backbuffer_index().

Józef Kucia jkucia at codeweavers.com
Fri Mar 1 06:31:30 CST 2019


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 dlls/d3d12/tests/d3d12.c | 271 +++++++++++++++++++++++----------------
 1 file changed, 161 insertions(+), 110 deletions(-)

diff --git a/dlls/d3d12/tests/d3d12.c b/dlls/d3d12/tests/d3d12.c
index dec7cf855839..5cb9a2991639 100644
--- a/dlls/d3d12/tests/d3d12.c
+++ b/dlls/d3d12/tests/d3d12.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <assert.h>
 #include <stdlib.h>
 #define COBJMACROS
 #include "initguid.h"
@@ -274,37 +275,25 @@ static ID3D12PipelineState *create_pipeline_state_(unsigned int line, ID3D12Devi
     return pipeline_state;
 }
 
-#define reset_command_list(a, b) reset_command_list_(__LINE__, a, b)
-static void reset_command_list_(unsigned int line,
-        ID3D12GraphicsCommandList *list, ID3D12CommandAllocator *allocator)
-{
-    HRESULT hr;
-
-    hr = ID3D12CommandAllocator_Reset(allocator);
-    ok_(__FILE__, line)(hr == S_OK, "Failed to reset command allocator, hr %#x.\n", hr);
-    hr = ID3D12GraphicsCommandList_Reset(list, allocator, NULL);
-    ok_(__FILE__, line)(hr == S_OK, "Failed to reset command list, hr %#x.\n", hr);
-}
-
 struct test_context_desc
 {
     BOOL no_pipeline;
     const D3D12_SHADER_BYTECODE *ps;
 };
 
+#define MAX_FRAME_COUNT 4
+
 struct test_context
 {
     ID3D12Device *device;
 
     ID3D12CommandQueue *queue;
-    ID3D12CommandAllocator *allocator;
-    ID3D12GraphicsCommandList *list;
-
-    D3D12_RESOURCE_DESC render_target_desc;
-    ID3D12Resource *render_target;
+    ID3D12CommandAllocator *allocator[MAX_FRAME_COUNT];
+    ID3D12GraphicsCommandList *list[MAX_FRAME_COUNT];
 
     ID3D12DescriptorHeap *rtv_heap;
-    D3D12_CPU_DESCRIPTOR_HANDLE rtv;
+    D3D12_CPU_DESCRIPTOR_HANDLE rtv[MAX_FRAME_COUNT];
+    ID3D12Resource *render_target[MAX_FRAME_COUNT];
 
     ID3D12RootSignature *root_signature;
     ID3D12PipelineState *pipeline_state;
@@ -313,15 +302,43 @@ struct test_context
     RECT scissor_rect;
 };
 
-#define create_render_target(context, a, b) create_render_target_(__LINE__, context, a, b)
-static void create_render_target_(unsigned int line, struct test_context *context,
-        ID3D12Resource **render_target, const D3D12_CPU_DESCRIPTOR_HANDLE *rtv)
+#define reset_command_list(a, b) reset_command_list_(__LINE__, a, b)
+static void reset_command_list_(unsigned int line, struct test_context *context, unsigned int index)
+{
+    HRESULT hr;
+
+    assert(index < MAX_FRAME_COUNT);
+
+    hr = ID3D12CommandAllocator_Reset(context->allocator[index]);
+    ok_(__FILE__, line)(hr == S_OK, "Failed to reset command allocator, hr %#x.\n", hr);
+    hr = ID3D12GraphicsCommandList_Reset(context->list[index], context->allocator[index], NULL);
+    ok_(__FILE__, line)(hr == S_OK, "Failed to reset command list, hr %#x.\n", hr);
+}
+
+static void destroy_render_targets(struct test_context *context)
+{
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(context->render_target); ++i)
+    {
+        if (context->render_target[i])
+        {
+            ID3D12Resource_Release(context->render_target[i]);
+            context->render_target[i] = NULL;
+        }
+    }
+}
+
+#define create_render_target(context) create_render_target_(__LINE__, context)
+static void create_render_target_(unsigned int line, struct test_context *context)
 {
     D3D12_HEAP_PROPERTIES heap_properties;
     D3D12_RESOURCE_DESC resource_desc;
     D3D12_CLEAR_VALUE clear_value;
     HRESULT hr;
 
+    destroy_render_targets(context);
+
     memset(&heap_properties, 0, sizeof(heap_properties));
     heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT;
 
@@ -344,13 +361,13 @@ static void create_render_target_(unsigned int line, struct test_context *contex
     hr = ID3D12Device_CreateCommittedResource(context->device,
             &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc,
             D3D12_RESOURCE_STATE_RENDER_TARGET, &clear_value,
-            &IID_ID3D12Resource, (void **)render_target);
+            &IID_ID3D12Resource, (void **)&context->render_target[0]);
     ok_(__FILE__, line)(hr == S_OK, "Failed to create texture, hr %#x.\n", hr);
 
-    context->render_target_desc = resource_desc;
+    set_viewport(&context->viewport, 0.0f, 0.0f, resource_desc.Width, resource_desc.Height, 0.0f, 1.0f);
+    SetRect(&context->scissor_rect, 0, 0, resource_desc.Width, resource_desc.Height);
 
-    if (rtv)
-        ID3D12Device_CreateRenderTargetView(context->device, *render_target, NULL, *rtv);
+    ID3D12Device_CreateRenderTargetView(context->device, context->render_target[0], NULL, context->rtv[0]);
 }
 
 #define init_test_context(a, b) init_test_context_(__LINE__, a, b)
@@ -359,7 +376,9 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context,
 {
     D3D12_COMMAND_QUEUE_DESC command_queue_desc;
     D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc;
+    unsigned int rtv_size;
     ID3D12Device *device;
+    unsigned int i;
     HRESULT hr;
 
     memset(context, 0, sizeof(*context));
@@ -379,15 +398,21 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context,
             &IID_ID3D12CommandQueue, (void **)&context->queue);
     ok_(__FILE__, line)(hr == S_OK, "Failed to create command queue, hr %#x.\n", hr);
 
-    hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
-            &IID_ID3D12CommandAllocator, (void **)&context->allocator);
-    ok_(__FILE__, line)(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
+    for (i = 0; i < ARRAY_SIZE(context->allocator); ++i)
+    {
+        hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
+                &IID_ID3D12CommandAllocator, (void **)&context->allocator[i]);
+        ok_(__FILE__, line)(hr == S_OK, "Failed to create command allocator %u, hr %#x.\n", i, hr);
+    }
 
-    hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
-            context->allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list);
-    ok_(__FILE__, line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
+    for (i = 0; i < ARRAY_SIZE(context->list); ++i)
+    {
+        hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
+                context->allocator[i], NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list[i]);
+        ok_(__FILE__, line)(hr == S_OK, "Failed to create command list %u, hr %#x.\n", i, hr);
+    }
 
-    rtv_heap_desc.NumDescriptors = 16;
+    rtv_heap_desc.NumDescriptors = MAX_FRAME_COUNT;
     rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
     rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
     rtv_heap_desc.NodeMask = 0;
@@ -395,14 +420,12 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context,
             &IID_ID3D12DescriptorHeap, (void **)&context->rtv_heap);
     ok_(__FILE__, line)(hr == S_OK, "Failed to create descriptor heap, hr %#x.\n", hr);
 
-    context->rtv = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(context->rtv_heap);
-
-    create_render_target_(line, context, &context->render_target, &context->rtv);
-
-    set_viewport(&context->viewport, 0.0f, 0.0f,
-            context->render_target_desc.Width, context->render_target_desc.Height, 0.0f, 1.0f);
-    SetRect(&context->scissor_rect, 0, 0,
-            context->render_target_desc.Width, context->render_target_desc.Height);
+    rtv_size = ID3D12Device_GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+    for (i = 0; i < ARRAY_SIZE(context->rtv); ++i)
+    {
+        context->rtv[i] = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(context->rtv_heap);
+        context->rtv[i].ptr += i * rtv_size;
+    }
 
     context->root_signature = create_default_root_signature(device);
 
@@ -410,8 +433,7 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context,
         return TRUE;
 
     context->pipeline_state = create_pipeline_state_(line, device,
-            context->root_signature, context->render_target_desc.Format,
-            desc ? desc->ps : NULL);
+            context->root_signature, DXGI_FORMAT_B8G8R8A8_UNORM, desc ? desc->ps : NULL);
 
     return TRUE;
 }
@@ -419,6 +441,7 @@ static BOOL init_test_context_(unsigned int line, struct test_context *context,
 #define destroy_test_context(context) destroy_test_context_(__LINE__, context)
 static void destroy_test_context_(unsigned int line, struct test_context *context)
 {
+    unsigned int i;
     ULONG refcount;
 
     if (context->pipeline_state)
@@ -428,12 +451,13 @@ static void destroy_test_context_(unsigned int line, struct test_context *contex
 
     if (context->rtv_heap)
         ID3D12DescriptorHeap_Release(context->rtv_heap);
-    if (context->render_target)
-        ID3D12Resource_Release(context->render_target);
+    destroy_render_targets(context);
 
-    ID3D12CommandAllocator_Release(context->allocator);
+    for (i = 0; i < ARRAY_SIZE(context->allocator); ++i)
+        ID3D12CommandAllocator_Release(context->allocator[i]);
     ID3D12CommandQueue_Release(context->queue);
-    ID3D12GraphicsCommandList_Release(context->list);
+    for (i = 0; i < ARRAY_SIZE(context->list); ++i)
+        ID3D12GraphicsCommandList_Release(context->list[i]);
 
     refcount = ID3D12Device_Release(context->device);
     ok_(__FILE__, line)(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
@@ -546,15 +570,22 @@ static HWND create_window(DWORD style)
     return CreateWindowA("static", "d3d12_test", style, 0, 0, 256, 256, NULL, NULL, NULL, NULL);
 }
 
-static IDXGISwapChain3 *create_swapchain(ID3D12CommandQueue *queue, HWND window,
-        DXGI_FORMAT format, unsigned int width, unsigned int height)
+static IDXGISwapChain3 *create_swapchain(struct test_context *context, HWND window,
+        unsigned int buffer_count, DXGI_FORMAT format, unsigned int width, unsigned int height)
 {
+    ID3D12CommandQueue *queue = context->queue;
+    ID3D12Device *device = context->device;
     IDXGISwapChain1 *swapchain1;
     DXGI_SWAP_CHAIN_DESC1 desc;
     IDXGISwapChain3 *swapchain;
     IDXGIFactory4 *factory;
+    unsigned int i;
     HRESULT hr;
 
+    assert(buffer_count <= MAX_FRAME_COUNT);
+
+    destroy_render_targets(context);
+
     hr = CreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory);
     ok(hr == S_OK, "Failed to create factory, hr %#x.\n", hr);
 
@@ -565,7 +596,7 @@ static IDXGISwapChain3 *create_swapchain(ID3D12CommandQueue *queue, HWND window,
     desc.SampleDesc.Count = 1;
     desc.SampleDesc.Quality = 0;
     desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    desc.BufferCount = 2;
+    desc.BufferCount = buffer_count;
     desc.Scaling = DXGI_SCALING_STRETCH;
     desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
     desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
@@ -578,6 +609,17 @@ static IDXGISwapChain3 *create_swapchain(ID3D12CommandQueue *queue, HWND window,
     hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain);
     ok(hr == S_OK, "Failed to query IDXGISwapChain3, hr %#x.\n", hr);
     IDXGISwapChain1_Release(swapchain1);
+
+    for (i = 0; i < buffer_count; ++i)
+    {
+        hr = IDXGISwapChain3_GetBuffer(swapchain, i, &IID_ID3D12Resource, (void **)&context->render_target[i]);
+        ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", i, hr);
+        ID3D12Device_CreateRenderTargetView(device, context->render_target[i], NULL, context->rtv[i]);
+    }
+
+    set_viewport(&context->viewport, 0.0f, 0.0f, width, height, 0.0f, 1.0f);
+    SetRect(&context->scissor_rect, 0, 0, width, height);
+
     return swapchain;
 }
 
@@ -768,12 +810,14 @@ static void test_draw(void)
 
     if (!init_test_context(&context, NULL))
         return;
-    command_list = context.list;
+    command_list = context.list[0];
     queue = context.queue;
 
-    ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
+    create_render_target(&context);
+
+    ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv[0], white, 0, NULL);
 
-    ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, FALSE, NULL);
+    ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv[0], FALSE, NULL);
     ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
     ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
     ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -781,10 +825,10 @@ static void test_draw(void)
     ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect);
     ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
 
-    transition_sub_resource_state(command_list, context.render_target, 0,
+    transition_sub_resource_state(command_list, context.render_target[0], 0,
             D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
 
-    check_sub_resource_uint(context.render_target, 0, queue, command_list, 0xff00ff00, 0);
+    check_sub_resource_uint(context.render_target[0], 0, queue, command_list, 0xff00ff00, 0);
 
     destroy_test_context(&context);
 }
@@ -793,6 +837,7 @@ static void test_swapchain_draw(void)
 {
     static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f};
     ID3D12GraphicsCommandList *command_list;
+    D3D12_CPU_DESCRIPTOR_HANDLE rtv;
     struct test_context_desc desc;
     struct test_context context;
     ID3D12Resource *backbuffer;
@@ -845,7 +890,7 @@ static void test_swapchain_draw(void)
     if (!init_test_context(&context, &desc))
         return;
     device = context.device;
-    command_list = context.list;
+    command_list = context.list[0];
     queue = context.queue;
 
     window = create_window(WS_VISIBLE);
@@ -858,18 +903,17 @@ static void test_swapchain_draw(void)
         context.pipeline_state = create_pipeline_state(device,
                 context.root_signature, tests[i].format, &ps);
 
-        swapchain = create_swapchain(queue, window, tests[i].format, rect.right, rect.bottom);
+        swapchain = create_swapchain(&context, window, 2, tests[i].format, rect.right, rect.bottom);
         index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
-        hr = IDXGISwapChain3_GetBuffer(swapchain, index, &IID_ID3D12Resource, (void **)&backbuffer);
-        ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", index, hr);
-        ID3D12Device_CreateRenderTargetView(device, backbuffer, NULL, context.rtv);
+        backbuffer = context.render_target[index];
+        rtv = context.rtv[index];
 
         transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
 
-        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
+        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, white, 0, NULL);
 
-        ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, FALSE, NULL);
+        ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv, FALSE, NULL);
         ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature);
         ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state);
         ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -882,7 +926,7 @@ static void test_swapchain_draw(void)
                 D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
         check_sub_resource_uint(backbuffer, 0, queue, command_list, tests[i].color, 0);
 
-        reset_command_list(command_list, context.allocator);
+        reset_command_list(&context, 0);
         transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT);
         hr = ID3D12GraphicsCommandList_Close(command_list);
@@ -894,14 +938,13 @@ static void test_swapchain_draw(void)
 
         wait_queue_idle(device, queue);
 
-        refcount = ID3D12Resource_Release(backbuffer);
-        ok(!refcount, "Backbuffer has %u references left.\n", refcount);
+        destroy_render_targets(&context);
         refcount = IDXGISwapChain3_Release(swapchain);
         ok(!refcount, "Swapchain has %u references left.\n", refcount);
         ID3D12PipelineState_Release(context.pipeline_state);
         context.pipeline_state = NULL;
 
-        reset_command_list(command_list, context.allocator);
+        reset_command_list(&context, 0);
     }
 
     DestroyWindow(window);
@@ -912,7 +955,7 @@ static void test_swapchain_size_mismatch(void)
 {
     static const float green[] = {0.0f, 1.0f, 0.0f, 1.0f};
     ID3D12GraphicsCommandList *command_list;
-    ID3D12Resource *backbuffers[2];
+    D3D12_CPU_DESCRIPTOR_HANDLE rtv;
     struct test_context_desc desc;
     struct test_context context;
     ID3D12Resource *backbuffer;
@@ -930,24 +973,23 @@ static void test_swapchain_size_mismatch(void)
     if (!init_test_context(&context, &desc))
         return;
     device = context.device;
-    command_list = context.list;
+    command_list = context.list[0];
     queue = context.queue;
 
     window = CreateWindowA("static", "d3d12_test", WS_VISIBLE, 0, 0, 200, 200, NULL, NULL, NULL, NULL);
-    swapchain = create_swapchain(queue, window, DXGI_FORMAT_B8G8R8A8_UNORM, 400, 400);
+    swapchain = create_swapchain(&context, window, 2, DXGI_FORMAT_B8G8R8A8_UNORM, 400, 400);
     index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
-    hr = IDXGISwapChain3_GetBuffer(swapchain, index, &IID_ID3D12Resource, (void **)&backbuffer);
-    ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", index, hr);
-    ID3D12Device_CreateRenderTargetView(device, backbuffer, NULL, context.rtv);
+    backbuffer = context.render_target[index];
+    rtv = context.rtv[index];
 
     transition_sub_resource_state(command_list, backbuffer, 0,
             D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
-    ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, green, 0, NULL);
+    ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, green, 0, NULL);
     transition_sub_resource_state(command_list, backbuffer, 0,
             D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
     check_sub_resource_uint(backbuffer, 0, queue, command_list, 0xff00ff00, 0);
 
-    reset_command_list(command_list, context.allocator);
+    reset_command_list(&context, 0);
     transition_sub_resource_state(command_list, backbuffer, 0,
             D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_PRESENT);
     hr = ID3D12GraphicsCommandList_Close(command_list);
@@ -958,10 +1000,9 @@ static void test_swapchain_size_mismatch(void)
     ok(hr == S_OK, "Failed to present, hr %#x.\n", hr);
 
     wait_queue_idle(device, queue);
-    reset_command_list(command_list, context.allocator);
+    reset_command_list(&context, 0);
 
-    refcount = ID3D12Resource_Release(backbuffer);
-    ok(!refcount, "Backbuffer has %u references left.\n", refcount);
+    destroy_render_targets(&context);
     refcount = IDXGISwapChain3_Release(swapchain);
     ok(!refcount, "Swapchain has %u references left.\n", refcount);
     DestroyWindow(window);
@@ -969,23 +1010,18 @@ static void test_swapchain_size_mismatch(void)
     window = create_window(WS_VISIBLE);
     ret = GetClientRect(window, &rect);
     ok(ret, "Failed to get client rect.\n");
-    swapchain = create_swapchain(queue, window, DXGI_FORMAT_B8G8R8A8_UNORM, rect.right, rect.bottom);
-
-    for (i = 0; i < ARRAY_SIZE(backbuffers); ++i)
-    {
-        hr = IDXGISwapChain3_GetBuffer(swapchain, i, &IID_ID3D12Resource, (void **)&backbuffers[i]);
-        ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", i, hr);
-    }
+    swapchain = create_swapchain(&context, window, 2, DXGI_FORMAT_B8G8R8A8_UNORM, rect.right, rect.bottom);
 
     for (i = 0; i < 20; ++i)
     {
         index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
-        ID3D12Device_CreateRenderTargetView(device, backbuffers[index], NULL, context.rtv);
+        backbuffer = context.render_target[index];
+        rtv = context.rtv[index];
 
-        transition_sub_resource_state(command_list, backbuffers[index], 0,
+        transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
-        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, green, 0, NULL);
-        transition_sub_resource_state(command_list, backbuffers[index], 0,
+        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, green, 0, NULL);
+        transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
         hr = ID3D12GraphicsCommandList_Close(command_list);
         ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr);
@@ -995,14 +1031,13 @@ static void test_swapchain_size_mismatch(void)
         ok(hr == S_OK, "Failed to present, hr %#x.\n", hr);
 
         wait_queue_idle(device, queue);
-        reset_command_list(command_list, context.allocator);
+        reset_command_list(&context, 0);
 
         if (i == 6)
             MoveWindow(window, 0, 0, 100, 100, TRUE);
     }
 
-    for (i = 0; i < ARRAY_SIZE(backbuffers); ++i)
-        ID3D12Resource_Release(backbuffers[i]);
+    destroy_render_targets(&context);
     refcount = IDXGISwapChain3_Release(swapchain);
     ok(!refcount, "Swapchain has %u references left.\n", refcount);
     DestroyWindow(window);
@@ -1012,15 +1047,20 @@ static void test_swapchain_size_mismatch(void)
 static void test_swapchain_backbuffer_index(void)
 {
     static const float green[] = {0.0f, 1.0f, 0.0f, 1.0f};
-    unsigned int previous_index, expected_index, index, i;
+    UINT64 frame_fence_value[MAX_FRAME_COUNT] = {0};
     ID3D12GraphicsCommandList *command_list;
-    ID3D12Resource *backbuffers[2];
+    unsigned int expected_index, index, i;
+    const unsigned int buffer_count = 2;
+    D3D12_CPU_DESCRIPTOR_HANDLE rtv;
     struct test_context_desc desc;
     struct test_context context;
+    ID3D12Resource *backbuffer;
     unsigned int sync_interval;
     IDXGISwapChain3 *swapchain;
     ID3D12CommandQueue *queue;
     ID3D12Device *device;
+    ID3D12Fence *fence;
+    UINT64 fence_value;
     ULONG refcount;
     HWND window;
     HRESULT hr;
@@ -1031,33 +1071,42 @@ static void test_swapchain_backbuffer_index(void)
     if (!init_test_context(&context, &desc))
         return;
     device = context.device;
-    command_list = context.list;
     queue = context.queue;
 
     window = create_window(WS_VISIBLE);
     ret = GetClientRect(window, &rect);
     ok(ret, "Failed to get client rect.\n");
-    swapchain = create_swapchain(queue, window, DXGI_FORMAT_B8G8R8A8_UNORM, rect.right, rect.bottom);
+    swapchain = create_swapchain(&context, window, buffer_count, DXGI_FORMAT_B8G8R8A8_UNORM, rect.right, rect.bottom);
 
-    for (i = 0; i < ARRAY_SIZE(backbuffers); ++i)
+    hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, (void **)&fence);
+    ok(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
+
+    for (i = 0; i < ARRAY_SIZE(context.list); ++i)
     {
-        hr = IDXGISwapChain3_GetBuffer(swapchain, i, &IID_ID3D12Resource, (void **)&backbuffers[i]);
-        ok(hr == S_OK, "Failed to get swapchain buffer %u, hr %#x.\n", i, hr);
+        hr = ID3D12GraphicsCommandList_Close(context.list[i]);
+        ok(hr == S_OK, "Failed to close command list %u, hr %#x.\n", i, hr);
     }
 
-    previous_index = 1;
+    index = 1;
+    fence_value = 1;
     for (i = 0; i < 20; ++i)
     {
+        expected_index = (index + 1) % buffer_count;
         index = IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain);
-        ID3D12Device_CreateRenderTargetView(device, backbuffers[index], NULL, context.rtv);
-
-        expected_index = (previous_index + 1) % 2;
         ok(index == expected_index, "Test %u: Got index %u, expected %u.\n", i, index, expected_index);
 
-        transition_sub_resource_state(command_list, backbuffers[index], 0,
+        hr = wait_for_fence(fence, frame_fence_value[index]);
+        ok(hr == S_OK, "Failed to wait for fence, hr %#x.\n", hr);
+
+        reset_command_list(&context, index);
+        backbuffer = context.render_target[index];
+        command_list = context.list[index];
+        rtv = context.rtv[index];
+
+        transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
-        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, green, 0, NULL);
-        transition_sub_resource_state(command_list, backbuffers[index], 0,
+        ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv, green, 0, NULL);
+        transition_sub_resource_state(command_list, backbuffer, 0,
                 D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
         hr = ID3D12GraphicsCommandList_Close(command_list);
         ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr);
@@ -1071,14 +1120,16 @@ static void test_swapchain_backbuffer_index(void)
         hr = IDXGISwapChain3_Present(swapchain, sync_interval, 0);
         ok(hr == S_OK, "Failed to present, hr %#x.\n", hr);
 
-        wait_queue_idle(device, queue);
-        reset_command_list(command_list, context.allocator);
-
-        previous_index = index;
+        frame_fence_value[index] = fence_value;
+        hr = ID3D12CommandQueue_Signal(queue, fence, fence_value);
+        ok(hr == S_OK, "Failed to signal fence, hr %#x.\n", hr);
+        ++fence_value;
     }
 
-    for (i = 0; i < ARRAY_SIZE(backbuffers); ++i)
-        ID3D12Resource_Release(backbuffers[i]);
+    wait_queue_idle(device, queue);
+
+    ID3D12Fence_Release(fence);
+    destroy_render_targets(&context);
     refcount = IDXGISwapChain3_Release(swapchain);
     ok(!refcount, "Swapchain has %u references left.\n", refcount);
     DestroyWindow(window);
-- 
2.19.2




More information about the wine-devel mailing list