From: Giovanni Mascellani Subject: Re: [PATCH vkd3d v5 05/14] tests/shader_runner: Make the render target into a resource. Message-Id: Date: Wed, 8 Jun 2022 15:20:09 +0200 In-Reply-To: <20220607212923.787652-5-zfigura@codeweavers.com> References: <20220607212923.787652-1-zfigura@codeweavers.com> <20220607212923.787652-5-zfigura@codeweavers.com> Signed-off-by: Giovanni Mascellani Il 07/06/22 23:29, Zebediah Figura ha scritto: > Signed-off-by: Zebediah Figura > --- > v5: New patch. > > tests/shader_runner.c | 57 ++++++++++++++- > tests/shader_runner.h | 6 +- > tests/shader_runner_d3d11.c | 70 +++++++++--------- > tests/shader_runner_d3d12.c | 86 ++++++++++++++++------ > tests/shader_runner_d3d9.c | 69 +++++++++--------- > tests/shader_runner_vulkan.c | 133 ++++++++++++++++++++--------------- > 6 files changed, 270 insertions(+), 151 deletions(-) > > diff --git a/tests/shader_runner.c b/tests/shader_runner.c > index 83f804ad3..f367027f7 100644 > --- a/tests/shader_runner.c > +++ b/tests/shader_runner.c > @@ -317,7 +317,27 @@ void init_resource(struct resource *resource, const struct resource_params *para > { > resource->type = params->type; > resource->slot = params->slot; > + resource->format = params->format; > resource->size = params->data_size; > + resource->texel_size = params->texel_size; > + resource->width = params->width; > + resource->height = params->height; > +} > + > +static struct resource *get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot) > +{ > + struct resource *resource; > + size_t i; > + > + for (i = 0; i < runner->resource_count; ++i) > + { > + resource = runner->resources[i]; > + > + if (resource->type == type && resource->slot == slot) > + return resource; > + } > + > + return NULL; > } > > static void set_resource(struct shader_runner *runner, struct resource *resource) > @@ -373,6 +393,20 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) > "{\n" > "}"; > > + if (!get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0)) > + { > + memset(¶ms, 0, sizeof(params)); > + params.slot = 0; > + params.type = RESOURCE_TYPE_RENDER_TARGET; > + params.format = DXGI_FORMAT_R32G32B32A32_FLOAT; > + params.data_type = TEXTURE_DATA_FLOAT; > + params.texel_size = 16; > + params.width = RENDER_TARGET_WIDTH; > + params.height = RENDER_TARGET_HEIGHT; > + > + set_resource(runner, runner->ops->create_resource(runner, ¶ms)); > + } > + > vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity, > 1, sizeof(*runner->input_elements)); > element = &runner->input_elements[0]; > @@ -399,9 +433,24 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) > else if (match_string(line, "draw", &line)) > { > D3D_PRIMITIVE_TOPOLOGY topology; > + struct resource_params params; > unsigned int vertex_count; > char *rest; > > + if (!get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0)) > + { > + memset(¶ms, 0, sizeof(params)); > + params.slot = 0; > + params.type = RESOURCE_TYPE_RENDER_TARGET; > + params.format = DXGI_FORMAT_R32G32B32A32_FLOAT; > + params.data_type = TEXTURE_DATA_FLOAT; > + params.texel_size = 16; > + params.width = RENDER_TARGET_WIDTH; > + params.height = RENDER_TARGET_HEIGHT; > + > + set_resource(runner, runner->ops->create_resource(runner, ¶ms)); > + } > + > if (match_string(line, "triangle list", &line)) > topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; > else if (match_string(line, "triangle strip", &line)) > @@ -419,15 +468,19 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) > { > unsigned int left, top, right, bottom, ulps; > struct resource_readback *rb; > + struct resource *resource; > int ret, len; > RECT rect; > > if (runner->last_render_failed) > return; > > + resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0); > + rb = runner->ops->get_resource_readback(runner, resource); > + > if (match_string(line, "all", &line)) > { > - set_rect(&rect, 0, 0, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT); > + set_rect(&rect, 0, 0, resource->width, resource->height); > } > else if (sscanf(line, "( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4) > { > @@ -444,8 +497,6 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) > fatal_error("Malformed probe arguments '%s'.\n", line); > } > > - rb = runner->ops->get_rt_readback(runner); > - > if (match_string(line, "rgba", &line)) > { > struct vec4 v; > diff --git a/tests/shader_runner.h b/tests/shader_runner.h > index 60f894583..19a48ee85 100644 > --- a/tests/shader_runner.h > +++ b/tests/shader_runner.h > @@ -53,6 +53,7 @@ struct sampler > > enum resource_type > { > + RESOURCE_TYPE_RENDER_TARGET, > RESOURCE_TYPE_TEXTURE, > RESOURCE_TYPE_UAV, > RESOURCE_TYPE_VERTEX_BUFFER, > @@ -76,7 +77,10 @@ struct resource > unsigned int slot; > enum resource_type type; > > + DXGI_FORMAT format; > unsigned int size; > + unsigned int texel_size; > + unsigned int width, height; > }; > > struct input_element > @@ -124,7 +128,7 @@ struct shader_runner_ops > struct resource *(*create_resource)(struct shader_runner *runner, const struct resource_params *params); > void (*destroy_resource)(struct shader_runner *runner, struct resource *resource); > bool (*draw)(struct shader_runner *runner, D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count); > - struct resource_readback *(*get_rt_readback)(struct shader_runner *runner); > + struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, struct resource *resource); > void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb); > }; > > diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c > index b80a8b65f..8999622d3 100644 > --- a/tests/shader_runner_d3d11.c > +++ b/tests/shader_runner_d3d11.c > @@ -43,6 +43,8 @@ struct d3d11_resource > struct resource r; > > ID3D11Resource *resource; > + ID3D11Texture2D *texture; > + ID3D11RenderTargetView *rtv; > ID3D11ShaderResourceView *srv; > ID3D11UnorderedAccessView *uav; > }; > @@ -59,8 +61,6 @@ struct d3d11_shader_runner > ID3D11Device *device; > HWND window; > IDXGISwapChain *swapchain; > - ID3D11Texture2D *rt; > - ID3D11RenderTargetView *rtv; > ID3D11DeviceContext *immediate_context; > }; > > @@ -276,20 +276,8 @@ static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window) > > static BOOL init_test_context(struct d3d11_shader_runner *runner) > { > - const D3D11_TEXTURE2D_DESC texture_desc = > - { > - .Width = RENDER_TARGET_WIDTH, > - .Height = RENDER_TARGET_HEIGHT, > - .MipLevels = 1, > - .ArraySize = 1, > - .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, > - .SampleDesc.Count = 1, > - .Usage = D3D11_USAGE_DEFAULT, > - .BindFlags = D3D11_BIND_RENDER_TARGET, > - }; > unsigned int rt_width, rt_height; > D3D11_VIEWPORT vp; > - HRESULT hr; > RECT rect; > > memset(runner, 0, sizeof(*runner)); > @@ -308,16 +296,8 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner) > 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); > runner->swapchain = create_swapchain(runner->device, runner->window); > > - hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, &runner->rt); > - ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); > - > - hr = ID3D11Device_CreateRenderTargetView(runner->device, (ID3D11Resource *)runner->rt, NULL, &runner->rtv); > - ok(hr == S_OK, "Failed to create rendertarget view, hr %#lx.\n", hr); > - > ID3D11Device_GetImmediateContext(runner->device, &runner->immediate_context); > > - ID3D11DeviceContext_OMSetRenderTargets(runner->immediate_context, 1, &runner->rtv, NULL); > - > vp.TopLeftX = 0.0f; > vp.TopLeftY = 0.0f; > vp.Width = rt_width; > @@ -334,8 +314,6 @@ static void destroy_test_context(struct d3d11_shader_runner *runner) > ULONG ref; > > ID3D11DeviceContext_Release(runner->immediate_context); > - ID3D11RenderTargetView_Release(runner->rtv); > - ID3D11Texture2D_Release(runner->rt); > IDXGISwapChain_Release(runner->swapchain); > DestroyWindow(runner->window); > > @@ -379,6 +357,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co > > switch (params->type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > case RESOURCE_TYPE_TEXTURE: > case RESOURCE_TYPE_UAV: > { > @@ -393,17 +372,29 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co > desc.Usage = D3D11_USAGE_DEFAULT; > if (params->type == RESOURCE_TYPE_UAV) > desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; > + else if (params->type == RESOURCE_TYPE_RENDER_TARGET) > + desc.BindFlags = D3D11_BIND_RENDER_TARGET; > else > desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; > > - resource_data.pSysMem = params->data; > - resource_data.SysMemPitch = params->width * params->texel_size; > - resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch; > - > - hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, (ID3D11Texture2D **)&resource->resource); > + if (params->data) > + { > + resource_data.pSysMem = params->data; > + resource_data.SysMemPitch = params->width * params->texel_size; > + resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch; > + hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, &resource->texture); > + } > + else > + { > + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &resource->texture); > + } > ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); > + > + resource->resource = (ID3D11Resource *)resource->texture; > if (params->type == RESOURCE_TYPE_UAV) > hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->uav); > + else if (params->type == RESOURCE_TYPE_RENDER_TARGET) > + hr = ID3D11Device_CreateRenderTargetView(device, resource->resource, NULL, &resource->rtv); > else > hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv); > ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); > @@ -424,6 +415,8 @@ static void d3d11_runner_destroy_resource(struct shader_runner *r, struct resour > struct d3d11_resource *resource = d3d11_resource(res); > > ID3D11Resource_Release(resource->resource); > + if (resource->rtv) > + ID3D11RenderTargetView_Release(resource->rtv); > if (resource->srv) > ID3D11ShaderResourceView_Release(resource->srv); > if (resource->uav) > @@ -435,11 +428,13 @@ static bool d3d11_runner_draw(struct shader_runner *r, > D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count) > { > ID3D11UnorderedAccessView *uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; > + ID3D11RenderTargetView *rtvs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; > struct d3d11_shader_runner *runner = d3d11_shader_runner(r); > ID3D11DeviceContext *context = runner->immediate_context; > unsigned int min_uav_slot = ARRAY_SIZE(uavs); > ID3D11Device *device = runner->device; > ID3D10Blob *vs_code, *ps_code; > + unsigned int rtv_count = 0; > ID3D11Buffer *cb = NULL; > ID3D11VertexShader *vs; > ID3D11PixelShader *ps; > @@ -478,6 +473,11 @@ static bool d3d11_runner_draw(struct shader_runner *r, > > switch (resource->r.type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + rtvs[resource->r.slot] = resource->rtv; > + rtv_count = max(rtv_count, resource->r.slot + 1); > + break; > + > case RESOURCE_TYPE_TEXTURE: > ID3D11DeviceContext_PSSetShaderResources(context, resource->r.slot, 1, &resource->srv); > break; > @@ -494,8 +494,7 @@ static bool d3d11_runner_draw(struct shader_runner *r, > } > } > > - ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, > - D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, NULL, NULL, > + ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, rtv_count, rtvs, NULL, > min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL); > > for (i = 0; i < runner->r.sampler_count; ++i) > @@ -565,15 +564,16 @@ struct d3d11_resource_readback > ID3D11Resource *resource; > }; > > -static struct resource_readback *d3d11_runner_get_rt_readback(struct shader_runner *r) > +static struct resource_readback *d3d11_runner_get_resource_readback(struct shader_runner *r, struct resource *res) > { > struct d3d11_shader_runner *runner = d3d11_shader_runner(r); > struct d3d11_resource_readback *rb = malloc(sizeof(*rb)); > + struct d3d11_resource *resource = d3d11_resource(res); > D3D11_TEXTURE2D_DESC texture_desc; > D3D11_MAPPED_SUBRESOURCE map_desc; > HRESULT hr; > > - ID3D11Texture2D_GetDesc(runner->rt, &texture_desc); > + ID3D11Texture2D_GetDesc(resource->texture, &texture_desc); > texture_desc.Usage = D3D11_USAGE_STAGING; > texture_desc.BindFlags = 0; > texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; > @@ -581,7 +581,7 @@ static struct resource_readback *d3d11_runner_get_rt_readback(struct shader_runn > hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource); > ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); > > - ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, (ID3D11Resource *)runner->rt); > + ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource); > hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc); > ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr); > > @@ -608,7 +608,7 @@ static const struct shader_runner_ops d3d11_runner_ops = > .create_resource = d3d11_runner_create_resource, > .destroy_resource = d3d11_runner_destroy_resource, > .draw = d3d11_runner_draw, > - .get_rt_readback = d3d11_runner_get_rt_readback, > + .get_resource_readback = d3d11_runner_get_resource_readback, > .release_readback = d3d11_runner_release_readback, > }; > > diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c > index f97e7bde9..b916de3c2 100644 > --- a/tests/shader_runner_d3d12.c > +++ b/tests/shader_runner_d3d12.c > @@ -44,7 +44,7 @@ struct d3d12_shader_runner > > struct test_context test_context; > > - ID3D12DescriptorHeap *heap; > + ID3D12DescriptorHeap *heap, *rtv_heap; > }; > > static struct d3d12_shader_runner *d3d12_shader_runner(struct shader_runner *r) > @@ -94,6 +94,20 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co > > switch (params->type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + if (!runner->rtv_heap) > + runner->rtv_heap = create_cpu_descriptor_heap(device, > + D3D12_DESCRIPTOR_HEAP_TYPE_RTV, MAX_RESOURCE_DESCRIPTORS); > + > + if (params->slot >= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT) > + fatal_error("RTV slot %u is too high.\n", params->slot); > + > + resource->resource = create_default_texture(device, params->width, params->height, > + params->format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); > + ID3D12Device_CreateRenderTargetView(device, resource->resource, > + NULL, get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot)); > + break; > + > case RESOURCE_TYPE_TEXTURE: > if (!runner->heap) > runner->heap = create_gpu_descriptor_heap(device, > @@ -157,18 +171,19 @@ static bool d3d12_runner_draw(struct shader_runner *r, > struct d3d12_shader_runner *runner = d3d12_shader_runner(r); > struct test_context *test_context = &runner->test_context; > > + D3D12_CPU_DESCRIPTOR_HANDLE rtvs[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0}; > ID3D12GraphicsCommandList *command_list = test_context->list; > D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; > + D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = {0}; > D3D12_ROOT_PARAMETER root_params[3], *root_param; > ID3D12CommandQueue *queue = test_context->queue; > D3D12_INPUT_ELEMENT_DESC *input_element_descs; > D3D12_STATIC_SAMPLER_DESC static_samplers[1]; > ID3D12Device *device = test_context->device; > - D3D12_INPUT_LAYOUT_DESC input_layout; > static const float clear_color[4]; > + unsigned int uniform_index = 0; > ID3D10Blob *vs_code, *ps_code; > - D3D12_SHADER_BYTECODE vs, ps; > - unsigned int uniform_index; > + unsigned int rtv_count = 0; > ID3D12PipelineState *pso; > HRESULT hr; > size_t i; > @@ -192,6 +207,16 @@ static bool d3d12_runner_draw(struct shader_runner *r, > root_signature_desc.pStaticSamplers = static_samplers; > root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; > > + pso_desc.VS.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code); > + pso_desc.VS.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code); > + pso_desc.PS.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code); > + pso_desc.PS.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code); > + pso_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; > + pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK; > + pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; > + pso_desc.SampleDesc.Count = 1; > + pso_desc.SampleMask = ~(UINT)0; > + > if (runner->r.uniform_count) > { > uniform_index = root_signature_desc.NumParameters++; > @@ -231,6 +256,12 @@ static bool d3d12_runner_draw(struct shader_runner *r, > range->OffsetInDescriptorsFromTableStart = 0; > break; > > + case RESOURCE_TYPE_RENDER_TARGET: > + pso_desc.RTVFormats[resource->r.slot] = resource->r.format; > + pso_desc.NumRenderTargets = max(pso_desc.NumRenderTargets, resource->r.slot + 1); > + pso_desc.BlendState.RenderTarget[resource->r.slot].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; > + break; > + > case RESOURCE_TYPE_VERTEX_BUFFER: > break; > } > @@ -258,6 +289,8 @@ static bool d3d12_runner_draw(struct shader_runner *r, > hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature); > ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); > > + pso_desc.pRootSignature = test_context->root_signature; > + > input_element_descs = calloc(runner->r.input_element_count, sizeof(*input_element_descs)); > for (i = 0; i < runner->r.input_element_count; ++i) > { > @@ -272,15 +305,12 @@ static bool d3d12_runner_draw(struct shader_runner *r, > desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; > } > > - input_layout.pInputElementDescs = input_element_descs; > - input_layout.NumElements = runner->r.input_element_count; > + pso_desc.InputLayout.pInputElementDescs = input_element_descs; > + pso_desc.InputLayout.NumElements = runner->r.input_element_count; > > - vs.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code); > - vs.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code); > - ps.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code); > - ps.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code); > - pso = create_pipeline_state(device, test_context->root_signature, > - test_context->render_target_desc.Format, &vs, &ps, &input_layout); > + hr = ID3D12Device_CreateGraphicsPipelineState(device, &pso_desc, > + &IID_ID3D12PipelineState, (void **)&pso); > + ok(hr == S_OK, "Failed to create state, hr %#x.\n", hr); > ID3D10Blob_Release(vs_code); > ID3D10Blob_Release(ps_code); > free(input_element_descs); > @@ -299,6 +329,13 @@ static bool d3d12_runner_draw(struct shader_runner *r, > > switch (resource->r.type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + rtvs[resource->r.slot] = get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.slot); > + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, > + rtvs[resource->r.slot], clear_color, 0, NULL); > + rtv_count = max(rtv_count, resource->r.slot + 1); > + break; > + > case RESOURCE_TYPE_TEXTURE: > ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, > get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); > @@ -320,11 +357,11 @@ static bool d3d12_runner_draw(struct shader_runner *r, > } > } > > - ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &test_context->rtv, false, NULL); > + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, rtv_count, rtvs, false, NULL); > + > ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &test_context->scissor_rect); > ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &test_context->viewport); > ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, primitive_topology); > - ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, test_context->rtv, clear_color, 0, NULL); > ID3D12GraphicsCommandList_SetPipelineState(command_list, pso); > ID3D12GraphicsCommandList_DrawInstanced(command_list, vertex_count, 1, 0, 0); > > @@ -338,16 +375,22 @@ static bool d3d12_runner_draw(struct shader_runner *r, > return true; > } > > -static struct resource_readback *d3d12_runner_get_rt_readback(struct shader_runner *r) > +static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, struct resource *res) > { > struct d3d12_shader_runner *runner = d3d12_shader_runner(r); > struct test_context *test_context = &runner->test_context; > struct d3d12_resource_readback *rb = malloc(sizeof(*rb)); > + struct d3d12_resource *resource = d3d12_resource(res); > > - transition_resource_state(test_context->list, test_context->render_target, > + assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET); > + > + transition_resource_state(test_context->list, resource->resource, > D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); > - get_texture_readback_with_command_list(test_context->render_target, 0, rb, > + get_texture_readback_with_command_list(resource->resource, 0, rb, > test_context->queue, test_context->list); > + reset_command_list(test_context->list, test_context->allocator); > + transition_resource_state(test_context->list, resource->resource, > + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); > > return &rb->rb; > } > @@ -355,13 +398,8 @@ static struct resource_readback *d3d12_runner_get_rt_readback(struct shader_runn > static void d3d12_runner_release_readback(struct shader_runner *r, struct resource_readback *rb) > { > struct d3d12_resource_readback *d3d12_rb = CONTAINING_RECORD(rb, struct d3d12_resource_readback, rb); > - struct d3d12_shader_runner *runner = d3d12_shader_runner(r); > - struct test_context *test_context = &runner->test_context; > > release_resource_readback(d3d12_rb); > - reset_command_list(test_context->list, test_context->allocator); > - transition_resource_state(test_context->list, test_context->render_target, > - D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); > free(d3d12_rb); > } > > @@ -370,7 +408,7 @@ static const struct shader_runner_ops d3d12_runner_ops = > .create_resource = d3d12_runner_create_resource, > .destroy_resource = d3d12_runner_destroy_resource, > .draw = d3d12_runner_draw, > - .get_rt_readback = d3d12_runner_get_rt_readback, > + .get_resource_readback = d3d12_runner_get_resource_readback, > .release_readback = d3d12_runner_release_readback, > }; > > @@ -394,5 +432,7 @@ void run_shader_tests_d3d12(int argc, char **argv) > > if (runner.heap) > ID3D12DescriptorHeap_Release(runner.heap); > + if (runner.rtv_heap) > + ID3D12DescriptorHeap_Release(runner.rtv_heap); > destroy_test_context(&runner.test_context); > } > diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c > index 417d68750..583b7ca73 100644 > --- a/tests/shader_runner_d3d9.c > +++ b/tests/shader_runner_d3d9.c > @@ -29,6 +29,7 @@ struct d3d9_resource > { > struct resource r; > > + IDirect3DSurface9 *surface; > IDirect3DTexture9 *texture; > IDirect3DVertexBuffer9 *vb; > }; > @@ -43,7 +44,6 @@ struct d3d9_shader_runner > struct shader_runner r; > > IDirect3DDevice9 *device; > - IDirect3DSurface9 *rt; > HWND window; > }; > > @@ -151,18 +151,6 @@ static bool init_test_context(struct d3d9_shader_runner *runner) > return false; > } > > - if (FAILED(hr = IDirect3DDevice9_CreateRenderTarget(runner->device, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT, > - D3DFMT_A32B32G32R32F, D3DMULTISAMPLE_NONE, 0, FALSE, &runner->rt, NULL))) > - { > - skip("Failed to create an A32B32G32R32F surface, hr %#lx.\n", hr); > - IDirect3DDevice9_Release(runner->device); > - DestroyWindow(runner->window); > - return false; > - } > - ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); > - hr = IDirect3DDevice9_SetRenderTarget(runner->device, 0, runner->rt); > - ok(hr == D3D_OK, "Failed to set render target, hr %#lx.\n", hr); > - > return true; > } > > @@ -170,7 +158,6 @@ static void destroy_test_context(struct d3d9_shader_runner *runner) > { > ULONG ref; > > - IDirect3DSurface9_Release(runner->rt); > ref = IDirect3DDevice9_Release(runner->device); > ok(!ref, "Device has %lu references left.\n", ref); > DestroyWindow(runner->window); > @@ -224,24 +211,30 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con > resource = calloc(1, sizeof(*resource)); > init_resource(&resource->r, params); > > + switch (params->format) > + { > + case DXGI_FORMAT_R32G32B32A32_FLOAT: > + format = D3DFMT_A32B32G32R32F; > + break; > + > + case DXGI_FORMAT_R32_FLOAT: > + format = D3DFMT_R32F; > + break; > + > + default: > + format = D3DFMT_UNKNOWN; > + break; > + } > + > switch (params->type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + hr = IDirect3DDevice9_CreateRenderTarget(device, params->width, params->height, > + format, D3DMULTISAMPLE_NONE, 0, FALSE, &resource->surface, NULL); > + ok(hr == D3D_OK, "Failed to create render target, hr %#lx.\n", hr); > + break; > + > case RESOURCE_TYPE_TEXTURE: > - switch (params->format) > - { > - case DXGI_FORMAT_R32G32B32A32_FLOAT: > - format = D3DFMT_A32B32G32R32F; > - break; > - > - case DXGI_FORMAT_R32_FLOAT: > - format = D3DFMT_R32F; > - break; > - > - default: > - format = D3DFMT_UNKNOWN; > - break; > - } > - > hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height, > 1, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL); > ok(hr == D3D_OK, "Failed to create texture, hr %#lx.\n", hr); > @@ -279,6 +272,8 @@ static void d3d9_runner_destroy_resource(struct shader_runner *r, struct resourc > { > struct d3d9_resource *resource = d3d9_resource(res); > > + if (resource->surface) > + IDirect3DSurface9_Release(resource->surface); > if (resource->texture) > IDirect3DTexture9_Release(resource->texture); > if (resource->vb) > @@ -363,6 +358,11 @@ static bool d3d9_runner_draw(struct shader_runner *r, > > switch (resource->r.type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + hr = IDirect3DDevice9_SetRenderTarget(device, resource->r.slot, resource->surface); > + ok(hr == D3D_OK, "Failed to set render target, hr %#lx.\n", hr); > + break; > + > case RESOURCE_TYPE_TEXTURE: > hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture); > ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr); > @@ -461,21 +461,24 @@ struct d3d9_resource_readback > IDirect3DSurface9 *surface; > }; > > -static struct resource_readback *d3d9_runner_get_rt_readback(struct shader_runner *r) > +static struct resource_readback *d3d9_runner_get_resource_readback(struct shader_runner *r, struct resource *res) > { > struct d3d9_shader_runner *runner = d3d9_shader_runner(r); > struct d3d9_resource_readback *rb = malloc(sizeof(*rb)); > + struct d3d9_resource *resource = d3d9_resource(res); > D3DLOCKED_RECT map_desc; > D3DSURFACE_DESC desc; > HRESULT hr; > > - hr = IDirect3DSurface9_GetDesc(runner->rt, &desc); > + assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET); > + > + hr = IDirect3DSurface9_GetDesc(resource->surface, &desc); > ok(hr == D3D_OK, "Failed to get surface desc, hr %#lx.\n", hr); > hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(runner->device, desc.Width, > desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL); > ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr); > > - hr = IDirect3DDevice9Ex_GetRenderTargetData(runner->device, runner->rt, rb->surface); > + hr = IDirect3DDevice9Ex_GetRenderTargetData(runner->device, resource->surface, rb->surface); > ok(hr == D3D_OK, "Failed to get render target data, hr %#lx.\n", hr); > > hr = IDirect3DSurface9_LockRect(rb->surface, &map_desc, NULL, D3DLOCK_READONLY); > @@ -504,7 +507,7 @@ static const struct shader_runner_ops d3d9_runner_ops = > .create_resource = d3d9_runner_create_resource, > .destroy_resource = d3d9_runner_destroy_resource, > .draw = d3d9_runner_draw, > - .get_rt_readback = d3d9_runner_get_rt_readback, > + .get_resource_readback = d3d9_runner_get_resource_readback, > .release_readback = d3d9_runner_release_readback, > }; > > diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c > index d62792d65..adb69a7ce 100644 > --- a/tests/shader_runner_vulkan.c > +++ b/tests/shader_runner_vulkan.c > @@ -60,10 +60,6 @@ struct vulkan_shader_runner > VkCommandBuffer cmd_buffer; > VkDescriptorPool descriptor_pool; > > - VkImage render_target; > - VkDeviceMemory rt_memory; > - VkImageView rtv; > - > struct vulkan_sampler > { > VkSampler vk_sampler; > @@ -247,6 +243,19 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c > > switch (params->type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > + format = vkd3d_get_vk_format(params->format); > + > + resource->image = create_2d_image(runner, params->width, params->height, > + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory); > + resource->view = create_2d_image_view(runner, resource->image, format); > + > + begin_command_buffer(runner); > + transition_image_layout(runner, resource->image, > + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); > + end_command_buffer(runner); > + break; > + > case RESOURCE_TYPE_TEXTURE: > case RESOURCE_TYPE_UAV: > { > @@ -385,6 +394,7 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char > > switch (resource->r.type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > case RESOURCE_TYPE_VERTEX_BUFFER: > break; > > @@ -514,7 +524,7 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR > VkPipelineViewportStateCreateInfo vp_desc = {.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO}; > static const VkRect2D rt_rect = {.extent.width = RENDER_TARGET_WIDTH, .extent.height = RENDER_TARGET_HEIGHT}; > VkGraphicsPipelineCreateInfo pipeline_desc = {.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; > - VkPipelineColorBlendAttachmentState attachment_desc = {0}; > + VkPipelineColorBlendAttachmentState attachment_desc[MAX_RESOURCES] = {0}; > VkVertexInputAttributeDescription input_attributes[32]; > VkVertexInputBindingDescription input_bindings[32]; > struct vkd3d_shader_signature vs_input_signature; > @@ -560,6 +570,9 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR > input_desc.pVertexAttributeDescriptions = input_attributes; > input_desc.pVertexBindingDescriptions = input_bindings; > > + blend_desc.attachmentCount = 0; > + blend_desc.pAttachments = attachment_desc; > + > for (i = 0; i < runner->r.resource_count; ++i) > { > const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]); > @@ -570,6 +583,12 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR > case RESOURCE_TYPE_UAV: > break; > > + case RESOURCE_TYPE_RENDER_TARGET: > + attachment_desc[blend_desc.attachmentCount++].colorWriteMask = > + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT > + | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; > + break; > + > case RESOURCE_TYPE_VERTEX_BUFFER: > { > VkVertexInputBindingDescription *binding = &input_bindings[input_desc.vertexBindingDescriptionCount++]; > @@ -603,12 +622,6 @@ static VkPipeline create_pipeline(const struct vulkan_shader_runner *runner, VkR > > ms_desc.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; > > - blend_desc.attachmentCount = 1; > - blend_desc.pAttachments = &attachment_desc; > - > - attachment_desc.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT > - | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; > - > pipeline_desc.stageCount = ARRAY_SIZE(stage_desc); > pipeline_desc.pStages = stage_desc; > pipeline_desc.pVertexInputState = &input_desc; > @@ -669,6 +682,7 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r > > switch (resource->r.type) > { > + case RESOURCE_TYPE_RENDER_TARGET: > case RESOURCE_TYPE_VERTEX_BUFFER: > break; > > @@ -768,6 +782,9 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo > if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) > VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.slot, 1, &resource->buffer, &zero_offset)); > break; > + > + case RESOURCE_TYPE_RENDER_TARGET: > + break; > } > } > > @@ -785,36 +802,53 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn > { > VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}; > VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; > - VkAttachmentDescription attachment_desc = {0}; > + VkAttachmentDescription attachment_descs[MAX_RESOURCES] = {0}; > + VkAttachmentReference color_refs[MAX_RESOURCES] = {0}; > VkSubpassDescription subpass_desc = {0}; > - VkAttachmentReference color_ref = {0}; > + VkImageView rtvs[MAX_RESOURCES]; > + unsigned int rt_count = 0; > + unsigned int i; > > - attachment_desc.format = VK_FORMAT_R32G32B32A32_SFLOAT; > - attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; > - attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; > - attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; > - attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; > - attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; > - attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > - attachment_desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > + for (i = 0; i < runner->r.resource_count; ++i) > + { > + const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]); > + VkAttachmentDescription *attachment_desc = &attachment_descs[rt_count]; > + VkAttachmentReference *color_ref = &color_refs[rt_count]; > > - color_ref.attachment = 0; > - color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > + if (resource->r.type != RESOURCE_TYPE_RENDER_TARGET) > + continue; > + > + attachment_desc->format = vkd3d_get_vk_format(resource->r.format); > + attachment_desc->samples = VK_SAMPLE_COUNT_1_BIT; > + attachment_desc->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; > + attachment_desc->storeOp = VK_ATTACHMENT_STORE_OP_STORE; > + attachment_desc->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; > + attachment_desc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; > + attachment_desc->initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > + attachment_desc->finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > + > + color_ref->attachment = rt_count; > + color_ref->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; > + > + rtvs[rt_count] = resource->view; > + > + ++rt_count; > + } > > subpass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; > - subpass_desc.colorAttachmentCount = 1; > - subpass_desc.pColorAttachments = &color_ref; > + subpass_desc.colorAttachmentCount = rt_count; > + subpass_desc.pColorAttachments = color_refs; > > - render_pass_desc.attachmentCount = 1; > - render_pass_desc.pAttachments = &attachment_desc; > + render_pass_desc.attachmentCount = rt_count; > + render_pass_desc.pAttachments = attachment_descs; > render_pass_desc.subpassCount = 1; > render_pass_desc.pSubpasses = &subpass_desc; > > VK_CALL(vkCreateRenderPass(runner->device, &render_pass_desc, NULL, render_pass)); > > fb_desc.renderPass = *render_pass; > - fb_desc.attachmentCount = 1; > - fb_desc.pAttachments = &runner->rtv; > + fb_desc.attachmentCount = rt_count; > + fb_desc.pAttachments = rtvs; > fb_desc.width = RENDER_TARGET_WIDTH; > fb_desc.height = RENDER_TARGET_HEIGHT; > fb_desc.layers = 1; > @@ -902,37 +936,40 @@ struct vulkan_resource_readback > VkBuffer buffer; > }; > > -static struct resource_readback *vulkan_runner_get_rt_readback(struct shader_runner *r) > +static struct resource_readback *vulkan_runner_get_resource_readback(struct shader_runner *r, struct resource *res) > { > struct vulkan_shader_runner *runner = vulkan_shader_runner(r); > struct vulkan_resource_readback *rb = malloc(sizeof(*rb)); > + struct vulkan_resource *resource = vulkan_resource(res); > VkDevice device = runner->device; > VkBufferImageCopy region = {0}; > > - rb->rb.width = RENDER_TARGET_WIDTH; > - rb->rb.height = RENDER_TARGET_HEIGHT; > + assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET); > + > + rb->rb.width = resource->r.width; > + rb->rb.height = resource->r.height; > rb->rb.depth = 1; > > - rb->rb.row_pitch = rb->rb.width * sizeof(struct vec4); > + rb->rb.row_pitch = rb->rb.width * resource->r.texel_size; > > - rb->buffer = create_buffer(runner, rb->rb.row_pitch * RENDER_TARGET_HEIGHT, > + rb->buffer = create_buffer(runner, rb->rb.row_pitch * rb->rb.height, > VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &rb->memory); > > begin_command_buffer(runner); > > - transition_image_layout(runner, runner->render_target, > + transition_image_layout(runner, resource->image, > VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); > > region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; > region.imageSubresource.layerCount = 1; > - region.imageExtent.width = RENDER_TARGET_WIDTH; > - region.imageExtent.height = RENDER_TARGET_HEIGHT; > + region.imageExtent.width = resource->r.width; > + region.imageExtent.height = resource->r.height; > region.imageExtent.depth = 1; > > - VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, runner->render_target, > + VK_CALL(vkCmdCopyImageToBuffer(runner->cmd_buffer, resource->image, > VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion)); > > - transition_image_layout(runner, runner->render_target, > + transition_image_layout(runner, resource->image, > VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); > > end_command_buffer(runner); > @@ -959,7 +996,7 @@ static const struct shader_runner_ops vulkan_runner_ops = > .create_resource = vulkan_runner_create_resource, > .destroy_resource = vulkan_runner_destroy_resource, > .draw = vulkan_runner_draw, > - .get_rt_readback = vulkan_runner_get_rt_readback, > + .get_resource_readback = vulkan_runner_get_resource_readback, > .release_readback = vulkan_runner_release_readback, > }; > > @@ -1141,11 +1178,6 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) > > VK_CALL(vkAllocateCommandBuffers(device, &cmd_buffer_desc, &runner->cmd_buffer)); > > - runner->render_target = create_2d_image(runner, RENDER_TARGET_WIDTH, RENDER_TARGET_HEIGHT, > - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, > - VK_FORMAT_R32G32B32A32_SFLOAT, &runner->rt_memory); > - runner->rtv = create_2d_image_view(runner, runner->render_target, VK_FORMAT_R32G32B32A32_SFLOAT); > - > descriptor_pool_sizes[0].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; > descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES; > descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER; > @@ -1159,13 +1191,6 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) > > VK_CALL(vkCreateDescriptorPool(device, &descriptor_pool_desc, NULL, &runner->descriptor_pool)); > > - begin_command_buffer(runner); > - > - transition_image_layout(runner, runner->render_target, > - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); > - > - end_command_buffer(runner); > - > return true; > > out_destroy_instance: > @@ -1177,10 +1202,6 @@ static void cleanup_vulkan_runner(struct vulkan_shader_runner *runner) > { > VkDevice device = runner->device; > > - VK_CALL(vkFreeMemory(device, runner->rt_memory, NULL)); > - VK_CALL(vkDestroyImageView(device, runner->rtv, NULL)); > - VK_CALL(vkDestroyImage(device, runner->render_target, NULL)); > - > VK_CALL(vkDestroyDescriptorPool(device, runner->descriptor_pool, NULL)); > VK_CALL(vkFreeCommandBuffers(device, runner->command_pool, 1, &runner->cmd_buffer)); > VK_CALL(vkDestroyCommandPool(device, runner->command_pool, NULL));