tests/shader_runner: Make the render target into a resource.

Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2022-06-08 18:18:37 -05:00 committed by Alexandre Julliard
parent d2d29d1b88
commit 2b69ee67bd
6 changed files with 270 additions and 151 deletions

View File

@ -317,7 +317,27 @@ void init_resource(struct resource *resource, const struct resource_params *para
{ {
resource->type = params->type; resource->type = params->type;
resource->slot = params->slot; resource->slot = params->slot;
resource->format = params->format;
resource->size = params->data_size; 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) 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" "{\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, vkd3d_array_reserve((void **)&runner->input_elements, &runner->input_element_capacity,
1, sizeof(*runner->input_elements)); 1, sizeof(*runner->input_elements));
element = &runner->input_elements[0]; 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)) else if (match_string(line, "draw", &line))
{ {
D3D_PRIMITIVE_TOPOLOGY topology; D3D_PRIMITIVE_TOPOLOGY topology;
struct resource_params params;
unsigned int vertex_count; unsigned int vertex_count;
char *rest; 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)) if (match_string(line, "triangle list", &line))
topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
else if (match_string(line, "triangle strip", &line)) 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; unsigned int left, top, right, bottom, ulps;
struct resource_readback *rb; struct resource_readback *rb;
struct resource *resource;
int ret, len; int ret, len;
RECT rect; RECT rect;
if (runner->last_render_failed) if (runner->last_render_failed)
return; return;
resource = get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0);
rb = runner->ops->get_resource_readback(runner, resource);
if (match_string(line, "all", &line)) 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) 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); fatal_error("Malformed probe arguments '%s'.\n", line);
} }
rb = runner->ops->get_rt_readback(runner);
if (match_string(line, "rgba", &line)) if (match_string(line, "rgba", &line))
{ {
struct vec4 v; struct vec4 v;

View File

@ -53,6 +53,7 @@ struct sampler
enum resource_type enum resource_type
{ {
RESOURCE_TYPE_RENDER_TARGET,
RESOURCE_TYPE_TEXTURE, RESOURCE_TYPE_TEXTURE,
RESOURCE_TYPE_UAV, RESOURCE_TYPE_UAV,
RESOURCE_TYPE_VERTEX_BUFFER, RESOURCE_TYPE_VERTEX_BUFFER,
@ -76,7 +77,10 @@ struct resource
unsigned int slot; unsigned int slot;
enum resource_type type; enum resource_type type;
DXGI_FORMAT format;
unsigned int size; unsigned int size;
unsigned int texel_size;
unsigned int width, height;
}; };
struct input_element struct input_element
@ -124,7 +128,7 @@ struct shader_runner_ops
struct resource *(*create_resource)(struct shader_runner *runner, const struct resource_params *params); struct resource *(*create_resource)(struct shader_runner *runner, const struct resource_params *params);
void (*destroy_resource)(struct shader_runner *runner, struct resource *resource); 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); 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); void (*release_readback)(struct shader_runner *runner, struct resource_readback *rb);
}; };

View File

@ -43,6 +43,8 @@ struct d3d11_resource
struct resource r; struct resource r;
ID3D11Resource *resource; ID3D11Resource *resource;
ID3D11Texture2D *texture;
ID3D11RenderTargetView *rtv;
ID3D11ShaderResourceView *srv; ID3D11ShaderResourceView *srv;
ID3D11UnorderedAccessView *uav; ID3D11UnorderedAccessView *uav;
}; };
@ -59,8 +61,6 @@ struct d3d11_shader_runner
ID3D11Device *device; ID3D11Device *device;
HWND window; HWND window;
IDXGISwapChain *swapchain; IDXGISwapChain *swapchain;
ID3D11Texture2D *rt;
ID3D11RenderTargetView *rtv;
ID3D11DeviceContext *immediate_context; 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) 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; unsigned int rt_width, rt_height;
D3D11_VIEWPORT vp; D3D11_VIEWPORT vp;
HRESULT hr;
RECT rect; RECT rect;
memset(runner, 0, sizeof(*runner)); 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); 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL);
runner->swapchain = create_swapchain(runner->device, runner->window); 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); ID3D11Device_GetImmediateContext(runner->device, &runner->immediate_context);
ID3D11DeviceContext_OMSetRenderTargets(runner->immediate_context, 1, &runner->rtv, NULL);
vp.TopLeftX = 0.0f; vp.TopLeftX = 0.0f;
vp.TopLeftY = 0.0f; vp.TopLeftY = 0.0f;
vp.Width = rt_width; vp.Width = rt_width;
@ -334,8 +314,6 @@ static void destroy_test_context(struct d3d11_shader_runner *runner)
ULONG ref; ULONG ref;
ID3D11DeviceContext_Release(runner->immediate_context); ID3D11DeviceContext_Release(runner->immediate_context);
ID3D11RenderTargetView_Release(runner->rtv);
ID3D11Texture2D_Release(runner->rt);
IDXGISwapChain_Release(runner->swapchain); IDXGISwapChain_Release(runner->swapchain);
DestroyWindow(runner->window); DestroyWindow(runner->window);
@ -379,6 +357,7 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co
switch (params->type) switch (params->type)
{ {
case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_TEXTURE:
case RESOURCE_TYPE_UAV: 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; desc.Usage = D3D11_USAGE_DEFAULT;
if (params->type == RESOURCE_TYPE_UAV) if (params->type == RESOURCE_TYPE_UAV)
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
else if (params->type == RESOURCE_TYPE_RENDER_TARGET)
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
else else
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
if (params->data)
{
resource_data.pSysMem = params->data; resource_data.pSysMem = params->data;
resource_data.SysMemPitch = params->width * params->texel_size; resource_data.SysMemPitch = params->width * params->texel_size;
resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch; resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch;
hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, &resource->texture);
hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, (ID3D11Texture2D **)&resource->resource); }
else
{
hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &resource->texture);
}
ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr);
resource->resource = (ID3D11Resource *)resource->texture;
if (params->type == RESOURCE_TYPE_UAV) if (params->type == RESOURCE_TYPE_UAV)
hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, NULL, &resource->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 else
hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv); hr = ID3D11Device_CreateShaderResourceView(device, resource->resource, NULL, &resource->srv);
ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); 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); struct d3d11_resource *resource = d3d11_resource(res);
ID3D11Resource_Release(resource->resource); ID3D11Resource_Release(resource->resource);
if (resource->rtv)
ID3D11RenderTargetView_Release(resource->rtv);
if (resource->srv) if (resource->srv)
ID3D11ShaderResourceView_Release(resource->srv); ID3D11ShaderResourceView_Release(resource->srv);
if (resource->uav) 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) D3D_PRIMITIVE_TOPOLOGY primitive_topology, unsigned int vertex_count)
{ {
ID3D11UnorderedAccessView *uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; 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); struct d3d11_shader_runner *runner = d3d11_shader_runner(r);
ID3D11DeviceContext *context = runner->immediate_context; ID3D11DeviceContext *context = runner->immediate_context;
unsigned int min_uav_slot = ARRAY_SIZE(uavs); unsigned int min_uav_slot = ARRAY_SIZE(uavs);
ID3D11Device *device = runner->device; ID3D11Device *device = runner->device;
ID3D10Blob *vs_code, *ps_code; ID3D10Blob *vs_code, *ps_code;
unsigned int rtv_count = 0;
ID3D11Buffer *cb = NULL; ID3D11Buffer *cb = NULL;
ID3D11VertexShader *vs; ID3D11VertexShader *vs;
ID3D11PixelShader *ps; ID3D11PixelShader *ps;
@ -478,6 +473,11 @@ static bool d3d11_runner_draw(struct shader_runner *r,
switch (resource->r.type) 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: case RESOURCE_TYPE_TEXTURE:
ID3D11DeviceContext_PSSetShaderResources(context, resource->r.slot, 1, &resource->srv); ID3D11DeviceContext_PSSetShaderResources(context, resource->r.slot, 1, &resource->srv);
break; break;
@ -494,8 +494,7 @@ static bool d3d11_runner_draw(struct shader_runner *r,
} }
} }
ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, ID3D11DeviceContext_OMSetRenderTargetsAndUnorderedAccessViews(context, rtv_count, rtvs, NULL,
D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, NULL, NULL,
min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL); min_uav_slot, ARRAY_SIZE(uavs) - min_uav_slot, &uavs[min_uav_slot], NULL);
for (i = 0; i < runner->r.sampler_count; ++i) for (i = 0; i < runner->r.sampler_count; ++i)
@ -565,15 +564,16 @@ struct d3d11_resource_readback
ID3D11Resource *resource; 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_shader_runner *runner = d3d11_shader_runner(r);
struct d3d11_resource_readback *rb = malloc(sizeof(*rb)); struct d3d11_resource_readback *rb = malloc(sizeof(*rb));
struct d3d11_resource *resource = d3d11_resource(res);
D3D11_TEXTURE2D_DESC texture_desc; D3D11_TEXTURE2D_DESC texture_desc;
D3D11_MAPPED_SUBRESOURCE map_desc; D3D11_MAPPED_SUBRESOURCE map_desc;
HRESULT hr; HRESULT hr;
ID3D11Texture2D_GetDesc(runner->rt, &texture_desc); ID3D11Texture2D_GetDesc(resource->texture, &texture_desc);
texture_desc.Usage = D3D11_USAGE_STAGING; texture_desc.Usage = D3D11_USAGE_STAGING;
texture_desc.BindFlags = 0; texture_desc.BindFlags = 0;
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; 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); hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource);
ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); 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); 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); 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, .create_resource = d3d11_runner_create_resource,
.destroy_resource = d3d11_runner_destroy_resource, .destroy_resource = d3d11_runner_destroy_resource,
.draw = d3d11_runner_draw, .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, .release_readback = d3d11_runner_release_readback,
}; };

View File

@ -44,7 +44,7 @@ struct d3d12_shader_runner
struct test_context test_context; struct test_context test_context;
ID3D12DescriptorHeap *heap; ID3D12DescriptorHeap *heap, *rtv_heap;
}; };
static struct d3d12_shader_runner *d3d12_shader_runner(struct shader_runner *r) 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) 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: case RESOURCE_TYPE_TEXTURE:
if (!runner->heap) if (!runner->heap)
runner->heap = create_gpu_descriptor_heap(device, runner->heap = create_gpu_descriptor_heap(device,
@ -150,18 +164,19 @@ static bool d3d12_runner_draw(struct shader_runner *r,
struct d3d12_shader_runner *runner = d3d12_shader_runner(r); struct d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *test_context = &runner->test_context; 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; ID3D12GraphicsCommandList *command_list = test_context->list;
D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = {0};
D3D12_ROOT_PARAMETER root_params[3], *root_param; D3D12_ROOT_PARAMETER root_params[3], *root_param;
ID3D12CommandQueue *queue = test_context->queue; ID3D12CommandQueue *queue = test_context->queue;
D3D12_INPUT_ELEMENT_DESC *input_element_descs; D3D12_INPUT_ELEMENT_DESC *input_element_descs;
D3D12_STATIC_SAMPLER_DESC static_samplers[1]; D3D12_STATIC_SAMPLER_DESC static_samplers[1];
ID3D12Device *device = test_context->device; ID3D12Device *device = test_context->device;
D3D12_INPUT_LAYOUT_DESC input_layout;
static const float clear_color[4]; static const float clear_color[4];
unsigned int uniform_index = 0;
ID3D10Blob *vs_code, *ps_code; ID3D10Blob *vs_code, *ps_code;
D3D12_SHADER_BYTECODE vs, ps; unsigned int rtv_count = 0;
unsigned int uniform_index;
ID3D12PipelineState *pso; ID3D12PipelineState *pso;
HRESULT hr; HRESULT hr;
size_t i; size_t i;
@ -185,6 +200,16 @@ static bool d3d12_runner_draw(struct shader_runner *r,
root_signature_desc.pStaticSamplers = static_samplers; root_signature_desc.pStaticSamplers = static_samplers;
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; 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) if (runner->r.uniform_count)
{ {
uniform_index = root_signature_desc.NumParameters++; uniform_index = root_signature_desc.NumParameters++;
@ -224,6 +249,12 @@ static bool d3d12_runner_draw(struct shader_runner *r,
range->OffsetInDescriptorsFromTableStart = 0; range->OffsetInDescriptorsFromTableStart = 0;
break; 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: case RESOURCE_TYPE_VERTEX_BUFFER:
break; break;
} }
@ -251,6 +282,8 @@ static bool d3d12_runner_draw(struct shader_runner *r,
hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature); 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); 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)); input_element_descs = calloc(runner->r.input_element_count, sizeof(*input_element_descs));
for (i = 0; i < runner->r.input_element_count; ++i) for (i = 0; i < runner->r.input_element_count; ++i)
{ {
@ -265,15 +298,12 @@ static bool d3d12_runner_draw(struct shader_runner *r,
desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA; desc->InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
} }
input_layout.pInputElementDescs = input_element_descs; pso_desc.InputLayout.pInputElementDescs = input_element_descs;
input_layout.NumElements = runner->r.input_element_count; pso_desc.InputLayout.NumElements = runner->r.input_element_count;
vs.pShaderBytecode = ID3D10Blob_GetBufferPointer(vs_code); hr = ID3D12Device_CreateGraphicsPipelineState(device, &pso_desc,
vs.BytecodeLength = ID3D10Blob_GetBufferSize(vs_code); &IID_ID3D12PipelineState, (void **)&pso);
ps.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code); ok(hr == S_OK, "Failed to create state, hr %#x.\n", hr);
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);
ID3D10Blob_Release(vs_code); ID3D10Blob_Release(vs_code);
ID3D10Blob_Release(ps_code); ID3D10Blob_Release(ps_code);
free(input_element_descs); free(input_element_descs);
@ -292,6 +322,13 @@ static bool d3d12_runner_draw(struct shader_runner *r,
switch (resource->r.type) 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: case RESOURCE_TYPE_TEXTURE:
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index,
get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot));
@ -312,11 +349,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_RSSetScissorRects(command_list, 1, &test_context->scissor_rect);
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &test_context->viewport); ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &test_context->viewport);
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, primitive_topology); ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, primitive_topology);
ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, test_context->rtv, clear_color, 0, NULL);
ID3D12GraphicsCommandList_SetPipelineState(command_list, pso); ID3D12GraphicsCommandList_SetPipelineState(command_list, pso);
ID3D12GraphicsCommandList_DrawInstanced(command_list, vertex_count, 1, 0, 0); ID3D12GraphicsCommandList_DrawInstanced(command_list, vertex_count, 1, 0, 0);
@ -330,16 +367,22 @@ static bool d3d12_runner_draw(struct shader_runner *r,
return true; 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 d3d12_shader_runner *runner = d3d12_shader_runner(r);
struct test_context *test_context = &runner->test_context; struct test_context *test_context = &runner->test_context;
struct d3d12_resource_readback *rb = malloc(sizeof(*rb)); 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); 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); 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; return &rb->rb;
} }
@ -347,13 +390,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) 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_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); 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); free(d3d12_rb);
} }
@ -362,7 +400,7 @@ static const struct shader_runner_ops d3d12_runner_ops =
.create_resource = d3d12_runner_create_resource, .create_resource = d3d12_runner_create_resource,
.destroy_resource = d3d12_runner_destroy_resource, .destroy_resource = d3d12_runner_destroy_resource,
.draw = d3d12_runner_draw, .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, .release_readback = d3d12_runner_release_readback,
}; };
@ -386,5 +424,7 @@ void run_shader_tests_d3d12(int argc, char **argv)
if (runner.heap) if (runner.heap)
ID3D12DescriptorHeap_Release(runner.heap); ID3D12DescriptorHeap_Release(runner.heap);
if (runner.rtv_heap)
ID3D12DescriptorHeap_Release(runner.rtv_heap);
destroy_test_context(&runner.test_context); destroy_test_context(&runner.test_context);
} }

View File

@ -29,6 +29,7 @@ struct d3d9_resource
{ {
struct resource r; struct resource r;
IDirect3DSurface9 *surface;
IDirect3DTexture9 *texture; IDirect3DTexture9 *texture;
IDirect3DVertexBuffer9 *vb; IDirect3DVertexBuffer9 *vb;
}; };
@ -43,7 +44,6 @@ struct d3d9_shader_runner
struct shader_runner r; struct shader_runner r;
IDirect3DDevice9 *device; IDirect3DDevice9 *device;
IDirect3DSurface9 *rt;
HWND window; HWND window;
}; };
@ -151,18 +151,6 @@ static bool init_test_context(struct d3d9_shader_runner *runner)
return false; 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; return true;
} }
@ -170,7 +158,6 @@ static void destroy_test_context(struct d3d9_shader_runner *runner)
{ {
ULONG ref; ULONG ref;
IDirect3DSurface9_Release(runner->rt);
ref = IDirect3DDevice9_Release(runner->device); ref = IDirect3DDevice9_Release(runner->device);
ok(!ref, "Device has %lu references left.\n", ref); ok(!ref, "Device has %lu references left.\n", ref);
DestroyWindow(runner->window); DestroyWindow(runner->window);
@ -224,9 +211,6 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
resource = calloc(1, sizeof(*resource)); resource = calloc(1, sizeof(*resource));
init_resource(&resource->r, params); init_resource(&resource->r, params);
switch (params->type)
{
case RESOURCE_TYPE_TEXTURE:
switch (params->format) switch (params->format)
{ {
case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -242,6 +226,15 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con
break; 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:
hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height, hr = IDirect3DDevice9_CreateTexture(device, params->width, params->height,
1, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL); 1, D3DUSAGE_DYNAMIC, format, D3DPOOL_DEFAULT, &resource->texture, NULL);
ok(hr == D3D_OK, "Failed to create texture, hr %#lx.\n", hr); 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); struct d3d9_resource *resource = d3d9_resource(res);
if (resource->surface)
IDirect3DSurface9_Release(resource->surface);
if (resource->texture) if (resource->texture)
IDirect3DTexture9_Release(resource->texture); IDirect3DTexture9_Release(resource->texture);
if (resource->vb) if (resource->vb)
@ -363,6 +358,11 @@ static bool d3d9_runner_draw(struct shader_runner *r,
switch (resource->r.type) 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: case RESOURCE_TYPE_TEXTURE:
hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture); hr = IDirect3DDevice9_SetTexture(device, resource->r.slot, (IDirect3DBaseTexture9 *)resource->texture);
ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr); ok(hr == D3D_OK, "Failed to set texture, hr %#lx.\n", hr);
@ -461,21 +461,24 @@ struct d3d9_resource_readback
IDirect3DSurface9 *surface; 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_shader_runner *runner = d3d9_shader_runner(r);
struct d3d9_resource_readback *rb = malloc(sizeof(*rb)); struct d3d9_resource_readback *rb = malloc(sizeof(*rb));
struct d3d9_resource *resource = d3d9_resource(res);
D3DLOCKED_RECT map_desc; D3DLOCKED_RECT map_desc;
D3DSURFACE_DESC desc; D3DSURFACE_DESC desc;
HRESULT hr; 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); ok(hr == D3D_OK, "Failed to get surface desc, hr %#lx.\n", hr);
hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(runner->device, desc.Width, hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(runner->device, desc.Width,
desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL); desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &rb->surface, NULL);
ok(hr == D3D_OK, "Failed to create surface, hr %#lx.\n", hr); 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); ok(hr == D3D_OK, "Failed to get render target data, hr %#lx.\n", hr);
hr = IDirect3DSurface9_LockRect(rb->surface, &map_desc, NULL, D3DLOCK_READONLY); 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, .create_resource = d3d9_runner_create_resource,
.destroy_resource = d3d9_runner_destroy_resource, .destroy_resource = d3d9_runner_destroy_resource,
.draw = d3d9_runner_draw, .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, .release_readback = d3d9_runner_release_readback,
}; };

View File

@ -60,10 +60,6 @@ struct vulkan_shader_runner
VkCommandBuffer cmd_buffer; VkCommandBuffer cmd_buffer;
VkDescriptorPool descriptor_pool; VkDescriptorPool descriptor_pool;
VkImage render_target;
VkDeviceMemory rt_memory;
VkImageView rtv;
struct vulkan_sampler struct vulkan_sampler
{ {
VkSampler vk_sampler; VkSampler vk_sampler;
@ -247,6 +243,19 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c
switch (params->type) 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_TEXTURE:
case RESOURCE_TYPE_UAV: case RESOURCE_TYPE_UAV:
{ {
@ -385,6 +394,7 @@ static bool compile_shader(const struct vulkan_shader_runner *runner, const char
switch (resource->r.type) switch (resource->r.type)
{ {
case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_VERTEX_BUFFER: case RESOURCE_TYPE_VERTEX_BUFFER:
break; 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}; 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}; 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}; 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]; VkVertexInputAttributeDescription input_attributes[32];
VkVertexInputBindingDescription input_bindings[32]; VkVertexInputBindingDescription input_bindings[32];
struct vkd3d_shader_signature vs_input_signature; 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.pVertexAttributeDescriptions = input_attributes;
input_desc.pVertexBindingDescriptions = input_bindings; input_desc.pVertexBindingDescriptions = input_bindings;
blend_desc.attachmentCount = 0;
blend_desc.pAttachments = attachment_desc;
for (i = 0; i < runner->r.resource_count; ++i) for (i = 0; i < runner->r.resource_count; ++i)
{ {
const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[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: case RESOURCE_TYPE_UAV:
break; 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: case RESOURCE_TYPE_VERTEX_BUFFER:
{ {
VkVertexInputBindingDescription *binding = &input_bindings[input_desc.vertexBindingDescriptionCount++]; 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; 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.stageCount = ARRAY_SIZE(stage_desc);
pipeline_desc.pStages = stage_desc; pipeline_desc.pStages = stage_desc;
pipeline_desc.pVertexInputState = &input_desc; pipeline_desc.pVertexInputState = &input_desc;
@ -669,6 +682,7 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r
switch (resource->r.type) switch (resource->r.type)
{ {
case RESOURCE_TYPE_RENDER_TARGET:
case RESOURCE_TYPE_VERTEX_BUFFER: case RESOURCE_TYPE_VERTEX_BUFFER:
break; break;
@ -768,6 +782,9 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo
if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS)
VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.slot, 1, &resource->buffer, &zero_offset)); VK_CALL(vkCmdBindVertexBuffers(cmd_buffer, resource->r.slot, 1, &resource->buffer, &zero_offset));
break; 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}; VkRenderPassCreateInfo render_pass_desc = {.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
VkFramebufferCreateInfo fb_desc = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_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}; 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; for (i = 0; i < runner->r.resource_count; ++i)
attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; {
attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; const struct vulkan_resource *resource = vulkan_resource(runner->r.resources[i]);
attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; VkAttachmentDescription *attachment_desc = &attachment_descs[rt_count];
attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; VkAttachmentReference *color_ref = &color_refs[rt_count];
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 = 0; if (resource->r.type != RESOURCE_TYPE_RENDER_TARGET)
color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 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.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_desc.colorAttachmentCount = 1; subpass_desc.colorAttachmentCount = rt_count;
subpass_desc.pColorAttachments = &color_ref; subpass_desc.pColorAttachments = color_refs;
render_pass_desc.attachmentCount = 1; render_pass_desc.attachmentCount = rt_count;
render_pass_desc.pAttachments = &attachment_desc; render_pass_desc.pAttachments = attachment_descs;
render_pass_desc.subpassCount = 1; render_pass_desc.subpassCount = 1;
render_pass_desc.pSubpasses = &subpass_desc; render_pass_desc.pSubpasses = &subpass_desc;
VK_CALL(vkCreateRenderPass(runner->device, &render_pass_desc, NULL, render_pass)); VK_CALL(vkCreateRenderPass(runner->device, &render_pass_desc, NULL, render_pass));
fb_desc.renderPass = *render_pass; fb_desc.renderPass = *render_pass;
fb_desc.attachmentCount = 1; fb_desc.attachmentCount = rt_count;
fb_desc.pAttachments = &runner->rtv; fb_desc.pAttachments = rtvs;
fb_desc.width = RENDER_TARGET_WIDTH; fb_desc.width = RENDER_TARGET_WIDTH;
fb_desc.height = RENDER_TARGET_HEIGHT; fb_desc.height = RENDER_TARGET_HEIGHT;
fb_desc.layers = 1; fb_desc.layers = 1;
@ -902,37 +936,40 @@ struct vulkan_resource_readback
VkBuffer buffer; 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_shader_runner *runner = vulkan_shader_runner(r);
struct vulkan_resource_readback *rb = malloc(sizeof(*rb)); struct vulkan_resource_readback *rb = malloc(sizeof(*rb));
struct vulkan_resource *resource = vulkan_resource(res);
VkDevice device = runner->device; VkDevice device = runner->device;
VkBufferImageCopy region = {0}; VkBufferImageCopy region = {0};
rb->rb.width = RENDER_TARGET_WIDTH; assert(resource->r.type == RESOURCE_TYPE_RENDER_TARGET);
rb->rb.height = RENDER_TARGET_HEIGHT;
rb->rb.width = resource->r.width;
rb->rb.height = resource->r.height;
rb->rb.depth = 1; 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); VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &rb->memory);
begin_command_buffer(runner); 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); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageExtent.width = RENDER_TARGET_WIDTH; region.imageExtent.width = resource->r.width;
region.imageExtent.height = RENDER_TARGET_HEIGHT; region.imageExtent.height = resource->r.height;
region.imageExtent.depth = 1; 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)); 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); VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
end_command_buffer(runner); end_command_buffer(runner);
@ -959,7 +996,7 @@ static const struct shader_runner_ops vulkan_runner_ops =
.create_resource = vulkan_runner_create_resource, .create_resource = vulkan_runner_create_resource,
.destroy_resource = vulkan_runner_destroy_resource, .destroy_resource = vulkan_runner_destroy_resource,
.draw = vulkan_runner_draw, .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, .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)); 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].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES; descriptor_pool_sizes[0].descriptorCount = MAX_RESOURCES;
descriptor_pool_sizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER; 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)); 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; return true;
out_destroy_instance: out_destroy_instance:
@ -1177,10 +1202,6 @@ static void cleanup_vulkan_runner(struct vulkan_shader_runner *runner)
{ {
VkDevice device = runner->device; 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(vkDestroyDescriptorPool(device, runner->descriptor_pool, NULL));
VK_CALL(vkFreeCommandBuffers(device, runner->command_pool, 1, &runner->cmd_buffer)); VK_CALL(vkFreeCommandBuffers(device, runner->command_pool, 1, &runner->cmd_buffer));
VK_CALL(vkDestroyCommandPool(device, runner->command_pool, NULL)); VK_CALL(vkDestroyCommandPool(device, runner->command_pool, NULL));