[PATCH vkd3d v5 05/14] tests/shader_runner: Make the render target into a resource.

Giovanni Mascellani gmascellani at codeweavers.com
Wed Jun 8 08:20:09 CDT 2022


Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>

Il 07/06/22 23:29, Zebediah Figura ha scritto:
> Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
> ---
> 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(&params, 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, &params));
> +        }
> +
>           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(&params, 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, &params));
> +        }
> +
>           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, &region));
>   
> -    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));



More information about the wine-devel mailing list