diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 1fa92210..486809bb 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -509,6 +509,7 @@ static void parse_input_layout_directive(struct shader_runner *runner, const cha void init_resource(struct resource *resource, const struct resource_params *params) { resource->type = params->type; + resource->dimension = params->dimension; resource->slot = params->slot; resource->format = params->format; resource->size = params->data_size; @@ -738,6 +739,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) memset(¶ms, 0, sizeof(params)); params.slot = 0; params.type = RESOURCE_TYPE_RENDER_TARGET; + params.dimension = RESOURCE_DIMENSION_2D; params.format = DXGI_FORMAT_R32G32B32A32_FLOAT; params.data_type = TEXTURE_DATA_FLOAT; params.texel_size = 16; @@ -764,6 +766,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) memset(¶ms, 0, sizeof(params)); params.slot = 0; params.type = RESOURCE_TYPE_VERTEX_BUFFER; + params.dimension = RESOURCE_DIMENSION_BUFFER; params.data = malloc(sizeof(quad)); memcpy(params.data, quad, sizeof(quad)); params.data_size = sizeof(quad); @@ -786,6 +789,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) memset(¶ms, 0, sizeof(params)); params.slot = 0; params.type = RESOURCE_TYPE_RENDER_TARGET; + params.dimension = RESOURCE_DIMENSION_2D; params.format = DXGI_FORMAT_R32G32B32A32_FLOAT; params.data_type = TEXTURE_DATA_FLOAT; params.texel_size = 16; @@ -838,7 +842,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) fatal_error("Malformed buffer UAV index '%s'.\n", line); line = rest; - resource = shader_runner_get_resource(runner, RESOURCE_TYPE_BUFFER_UAV, slot); + resource = shader_runner_get_resource(runner, RESOURCE_TYPE_UAV, slot); } else if (match_string(line, "render target", &line)) { @@ -1545,6 +1549,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.slot = index; current_resource.type = RESOURCE_TYPE_RENDER_TARGET; + current_resource.dimension = RESOURCE_DIMENSION_2D; current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; @@ -1558,6 +1563,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.slot = index; current_resource.type = RESOURCE_TYPE_TEXTURE; + current_resource.dimension = RESOURCE_DIMENSION_2D; current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; @@ -1571,6 +1577,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.slot = index; current_resource.type = RESOURCE_TYPE_UAV; + current_resource.dimension = RESOURCE_DIMENSION_2D; current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; @@ -1583,7 +1590,8 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o memset(¤t_resource, 0, sizeof(current_resource)); current_resource.slot = index; - current_resource.type = RESOURCE_TYPE_BUFFER_UAV; + current_resource.type = RESOURCE_TYPE_UAV; + current_resource.dimension = RESOURCE_DIMENSION_BUFFER; current_resource.format = DXGI_FORMAT_R32G32B32A32_FLOAT; current_resource.data_type = TEXTURE_DATA_FLOAT; current_resource.texel_size = 16; @@ -1597,6 +1605,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_o current_resource.slot = index; current_resource.type = RESOURCE_TYPE_VERTEX_BUFFER; + current_resource.dimension = RESOURCE_DIMENSION_BUFFER; current_resource.data_type = TEXTURE_DATA_FLOAT; } else if (!strcmp(line, "[test]\n")) diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 7e184fc5..da4b2efc 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -69,14 +69,20 @@ enum resource_type RESOURCE_TYPE_RENDER_TARGET, RESOURCE_TYPE_TEXTURE, RESOURCE_TYPE_UAV, - RESOURCE_TYPE_BUFFER_UAV, RESOURCE_TYPE_VERTEX_BUFFER, }; +enum resource_dimension +{ + RESOURCE_DIMENSION_BUFFER, + RESOURCE_DIMENSION_2D, +}; + struct resource_params { unsigned int slot; enum resource_type type; + enum resource_dimension dimension; DXGI_FORMAT format; enum texture_data_type data_type; @@ -91,6 +97,7 @@ struct resource { unsigned int slot; enum resource_type type; + enum resource_dimension dimension; DXGI_FORMAT format; unsigned int size; diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index d0d9e927..2e6b4ced 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -371,12 +371,87 @@ static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags return buffer; } +static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, + const struct resource_params *params) +{ + D3D11_SUBRESOURCE_DATA resource_data[2]; + ID3D11Device *device = runner->device; + D3D11_TEXTURE2D_DESC desc = {0}; + HRESULT hr; + + if (params->level_count > ARRAY_SIZE(resource_data)) + fatal_error("Level count %u is too high.\n", params->level_count); + + desc.Width = params->width; + desc.Height = params->height; + desc.MipLevels = params->level_count; + desc.ArraySize = 1; + desc.Format = params->format; + desc.SampleDesc.Count = 1; + 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; + + if (params->data) + { + unsigned int buffer_offset = 0; + + for (unsigned int level = 0; level < params->level_count; ++level) + { + unsigned int level_width = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(params->height, level); + + resource_data[level].pSysMem = ¶ms->data[buffer_offset]; + resource_data[level].SysMemPitch = level_width * params->texel_size; + resource_data[level].SysMemSlicePitch = level_height * resource_data[level].SysMemPitch; + buffer_offset += resource_data[level].SysMemSlicePitch; + } + 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); +} + +static void init_resource_uav_buffer(struct d3d11_shader_runner *runner, struct d3d11_resource *resource, + const struct resource_params *params) +{ + D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; + ID3D11Device *device = runner->device; + HRESULT hr; + + resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->data); + resource->resource = (ID3D11Resource *)resource->buffer; + + uav_desc.Format = params->format; + uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + uav_desc.Buffer.FirstElement = 0; + uav_desc.Buffer.NumElements = params->data_size / params->texel_size; + uav_desc.Buffer.Flags = 0; + hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, &uav_desc, &resource->uav); + ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); +} + static struct resource *d3d11_runner_create_resource(struct shader_runner *r, const struct resource_params *params) { struct d3d11_shader_runner *runner = d3d11_shader_runner(r); ID3D11Device *device = runner->device; struct d3d11_resource *resource; - HRESULT hr; resource = calloc(1, sizeof(*resource)); init_resource(&resource->r, params); @@ -385,77 +460,15 @@ static struct resource *d3d11_runner_create_resource(struct shader_runner *r, co { case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_TEXTURE: + init_resource_2d(runner, resource, params); + break; + case RESOURCE_TYPE_UAV: - { - D3D11_SUBRESOURCE_DATA resource_data[2]; - D3D11_TEXTURE2D_DESC desc = {0}; - - if (params->level_count > ARRAY_SIZE(resource_data)) - fatal_error("Level count %u is too high.\n", params->level_count); - - desc.Width = params->width; - desc.Height = params->height; - desc.MipLevels = params->level_count; - desc.ArraySize = 1; - desc.Format = params->format; - desc.SampleDesc.Count = 1; - 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; + if (params->dimension == RESOURCE_DIMENSION_BUFFER) + init_resource_uav_buffer(runner, resource, params); else - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - - if (params->data) - { - unsigned int buffer_offset = 0; - - for (unsigned int level = 0; level < params->level_count; ++level) - { - unsigned int level_width = get_level_dimension(params->width, level); - unsigned int level_height = get_level_dimension(params->height, level); - - resource_data[level].pSysMem = ¶ms->data[buffer_offset]; - resource_data[level].SysMemPitch = level_width * params->texel_size; - resource_data[level].SysMemSlicePitch = level_height * resource_data[level].SysMemPitch; - buffer_offset += resource_data[level].SysMemSlicePitch; - } - 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); + init_resource_2d(runner, resource, params); break; - } - - case RESOURCE_TYPE_BUFFER_UAV: - { - D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc; - - resource->buffer = create_buffer(device, D3D11_BIND_UNORDERED_ACCESS, params->data_size, params->data); - resource->resource = (ID3D11Resource *)resource->buffer; - - uav_desc.Format = params->format; - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.FirstElement = 0; - uav_desc.Buffer.NumElements = params->data_size / params->texel_size; - uav_desc.Buffer.Flags = 0; - hr = ID3D11Device_CreateUnorderedAccessView(device, resource->resource, &uav_desc, &resource->uav); - ok(hr == S_OK, "Failed to create view, hr %#lx.\n", hr); - break; - } case RESOURCE_TYPE_VERTEX_BUFFER: resource->buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, params->data_size, params->data); @@ -538,7 +551,6 @@ static bool d3d11_runner_dispatch(struct shader_runner *r, unsigned int x, unsig break; case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: ID3D11DeviceContext_CSSetUnorderedAccessViews(context, resource->r.slot, 1, &resource->uav, NULL); break; @@ -625,7 +637,6 @@ static bool d3d11_runner_draw(struct shader_runner *r, break; case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: uavs[resource->r.slot] = resource->uav; min_uav_slot = min(min_uav_slot, resource->r.slot); break; @@ -709,25 +720,28 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade switch (resource->r.type) { - case RESOURCE_TYPE_BUFFER_UAV: - ID3D11Buffer_GetDesc(resource->buffer, &buffer_desc); - buffer_desc.Usage = D3D11_USAGE_STAGING; - buffer_desc.BindFlags = 0; - buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - buffer_desc.MiscFlags = 0; - hr = ID3D11Device_CreateBuffer(runner->device, &buffer_desc, NULL, (ID3D11Buffer **)&rb->resource); - ok(hr == S_OK, "Failed to create buffer, hr %#lx.\n", hr); - break; - case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_UAV: - ID3D11Texture2D_GetDesc(resource->texture, &texture_desc); - texture_desc.Usage = D3D11_USAGE_STAGING; - texture_desc.BindFlags = 0; - texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - texture_desc.MiscFlags = 0; - hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource); - ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) + { + ID3D11Buffer_GetDesc(resource->buffer, &buffer_desc); + buffer_desc.Usage = D3D11_USAGE_STAGING; + buffer_desc.BindFlags = 0; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + buffer_desc.MiscFlags = 0; + hr = ID3D11Device_CreateBuffer(runner->device, &buffer_desc, NULL, (ID3D11Buffer **)&rb->resource); + ok(hr == S_OK, "Failed to create buffer, hr %#lx.\n", hr); + } + else + { + ID3D11Texture2D_GetDesc(resource->texture, &texture_desc); + texture_desc.Usage = D3D11_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource); + ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + } break; case RESOURCE_TYPE_VERTEX_BUFFER: diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 7ba61d11..c7f9d4f7 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -189,43 +189,41 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co runner->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS); - state = params->data ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - resource->resource = create_default_texture2d(device, params->width, params->height, 1, - params->level_count, params->format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, state); - if (params->data) + if (params->dimension == RESOURCE_DIMENSION_BUFFER) { - upload_texture_data_with_states(resource->resource, resource_data, - params->level_count, test_context->queue, test_context->list, + D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = { 0 }; + + resource->resource = create_default_buffer(device, params->data_size, + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST); + upload_buffer_data_with_states(resource->resource, 0, params->data_size, resource_data[0].pData, + test_context->queue, test_context->list, RESOURCE_STATE_DO_NOT_CHANGE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); reset_command_list(test_context->list, test_context->allocator); + + uav_desc.Format = params->format; + uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uav_desc.Buffer.NumElements = params->width * params->height; + + ID3D12Device_CreateUnorderedAccessView(device, resource->resource, + NULL, &uav_desc, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); + } + else + { + state = params->data ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, + params->format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, state); + if (params->data) + { + upload_texture_data_with_states(resource->resource, resource_data, + params->level_count, test_context->queue, test_context->list, + RESOURCE_STATE_DO_NOT_CHANGE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + reset_command_list(test_context->list, test_context->allocator); + } + ID3D12Device_CreateUnorderedAccessView(device, resource->resource, NULL, NULL, + get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); } - ID3D12Device_CreateUnorderedAccessView(device, resource->resource, NULL, NULL, - get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); break; - case RESOURCE_TYPE_BUFFER_UAV: - { - D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = { 0 }; - - if (!runner->heap) - runner->heap = create_gpu_descriptor_heap(device, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, MAX_RESOURCE_DESCRIPTORS); - - resource->resource = create_default_buffer(device, params->data_size, - D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST); - upload_buffer_data_with_states(resource->resource, 0, params->data_size, resource_data[0].pData, - test_context->queue, test_context->list, - RESOURCE_STATE_DO_NOT_CHANGE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - reset_command_list(test_context->list, test_context->allocator); - - uav_desc.Format = params->format; - uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - uav_desc.Buffer.NumElements = params->width * params->height; - - ID3D12Device_CreateUnorderedAccessView(device, resource->resource, - NULL, &uav_desc, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); - break; - } case RESOURCE_TYPE_VERTEX_BUFFER: resource->resource = create_upload_buffer(device, params->data_size, params->data); break; @@ -281,7 +279,6 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: range = &resource->descriptor_range; if (base_resource && resource->r.type == base_resource->r.type && resource->r.slot == slot + 1) @@ -299,7 +296,7 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad root_param->DescriptorTable.pDescriptorRanges = range; root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - if (resource->r.type == RESOURCE_TYPE_UAV || resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.type == RESOURCE_TYPE_UAV) range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; else range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; @@ -403,7 +400,6 @@ static bool d3d12_runner_dispatch(struct shader_runner *r, unsigned int x, unsig break; case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: if (resource->descriptor_range.NumDescriptors) ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(command_list, resource->root_index, get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); @@ -546,7 +542,6 @@ static bool d3d12_runner_draw(struct shader_runner *r, break; case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: if (resource->descriptor_range.NumDescriptors) ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, resource->root_index, get_gpu_descriptor_handle(test_context, runner->heap, resource->r.slot + MAX_RESOURCES)); diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 824aca01..773a27ff 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -267,7 +267,6 @@ static struct resource *d3d9_runner_create_resource(struct shader_runner *r, con } case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: fatal_error("UAVs are not supported.\n"); break; @@ -393,7 +392,6 @@ static bool d3d9_runner_draw(struct shader_runner *r, break; case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: vkd3d_unreachable(); case RESOURCE_TYPE_VERTEX_BUFFER: diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 13bbf2e3..3ce319b9 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -328,10 +328,46 @@ static const struct format_info *get_format_info(enum DXGI_FORMAT format) fatal_error("Failed to find format info for format %#x.\n", format); } +static void init_resource_2d(struct gl_resource *resource, const struct resource_params *params) +{ + unsigned int offset, w, h, i; + + resource->format = get_format_info(params->format); + glGenTextures(1, &resource->id); + glBindTexture(GL_TEXTURE_2D, resource->id); + glTexStorage2D(GL_TEXTURE_2D, params->level_count, + resource->format->internal_format, params->width, params->height); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + if (!params->data) + return; + + for (i = 0, offset = 0; i < params->level_count; ++i) + { + w = get_level_dimension(params->width, i); + h = get_level_dimension(params->height, i); + glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, w, h, resource->format->format, + resource->format->type, params->data + offset); + offset += w * h * params->texel_size; + } +} + +static void init_resource_buffer(struct gl_resource *resource, const struct resource_params *params) +{ + resource->format = get_format_info(params->format); + + glGenBuffers(1, &resource->id); + glBindBuffer(GL_TEXTURE_BUFFER, resource->id); + glBufferData(GL_TEXTURE_BUFFER, params->data_size, params->data, GL_STATIC_DRAW); + + glGenTextures(1, &resource->tbo_id); + glBindTexture(GL_TEXTURE_BUFFER, resource->tbo_id); + glTexBuffer(GL_TEXTURE_BUFFER, resource->format->internal_format, resource->id); +} + static struct resource *gl_runner_create_resource(struct shader_runner *r, const struct resource_params *params) { struct gl_resource *resource; - unsigned int offset, w, h, i; resource = calloc(1, sizeof(*resource)); init_resource(&resource->r, params); @@ -340,37 +376,14 @@ static struct resource *gl_runner_create_resource(struct shader_runner *r, const { case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_TEXTURE: - case RESOURCE_TYPE_UAV: - resource->format = get_format_info(params->format); - glGenTextures(1, &resource->id); - glBindTexture(GL_TEXTURE_2D, resource->id); - glTexStorage2D(GL_TEXTURE_2D, params->level_count, - resource->format->internal_format, params->width, params->height); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - if (!params->data) - break; - - for (i = 0, offset = 0; i < params->level_count; ++i) - { - w = get_level_dimension(params->width, i); - h = get_level_dimension(params->height, i); - glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, w, h, resource->format->format, - resource->format->type, params->data + offset); - offset += w * h * params->texel_size; - } + init_resource_2d(resource, params); break; - case RESOURCE_TYPE_BUFFER_UAV: - resource->format = get_format_info(params->format); - - glGenBuffers(1, &resource->id); - glBindBuffer(GL_TEXTURE_BUFFER, resource->id); - glBufferData(GL_TEXTURE_BUFFER, params->data_size, params->data, GL_STATIC_DRAW); - - glGenTextures(1, &resource->tbo_id); - glBindTexture(GL_TEXTURE_BUFFER, resource->tbo_id); - glTexBuffer(GL_TEXTURE_BUFFER, resource->format->internal_format, resource->id); + case RESOURCE_TYPE_UAV: + if (params->dimension == RESOURCE_DIMENSION_BUFFER) + init_resource_buffer(resource, params); + else + init_resource_2d(resource, params); break; case RESOURCE_TYPE_VERTEX_BUFFER: @@ -391,13 +404,21 @@ static void gl_runner_destroy_resource(struct shader_runner *r, struct resource { case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_TEXTURE: - case RESOURCE_TYPE_UAV: glDeleteTextures(1, &resource->id); break; - case RESOURCE_TYPE_BUFFER_UAV: - glDeleteTextures(1, &resource->tbo_id); - /* Fall-through. */ + case RESOURCE_TYPE_UAV: + if (res->dimension == RESOURCE_DIMENSION_BUFFER) + { + glDeleteTextures(1, &resource->tbo_id); + glDeleteBuffers(1, &resource->id); + } + else + { + glDeleteTextures(1, &resource->id); + } + break; + case RESOURCE_TYPE_VERTEX_BUFFER: glDeleteBuffers(1, &resource->id); break; @@ -515,13 +536,12 @@ static bool compile_shader(struct gl_runner *runner, ID3DBlob *blob, struct vkd3 switch (resource->r.type) { case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: binding = &bindings[interface_info.binding_count++]; binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; binding->register_space = 0; binding->register_index = resource->r.slot; binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL; - if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) binding->flags = VKD3D_SHADER_BINDING_FLAG_BUFFER; else binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE; @@ -650,16 +670,13 @@ static bool gl_runner_dispatch(struct shader_runner *r, unsigned int x, unsigned { case RESOURCE_TYPE_RENDER_TARGET: case RESOURCE_TYPE_VERTEX_BUFFER: - break; - case RESOURCE_TYPE_TEXTURE: - case RESOURCE_TYPE_BUFFER_UAV: - trace("RESOURCE TYPE %#x.\n", resource->r.type); break; case RESOURCE_TYPE_UAV: - glBindImageTexture(resource->r.slot, resource->id, 0, GL_TRUE, - 0, GL_READ_WRITE, resource->format->internal_format); + if (resource->r.dimension != RESOURCE_DIMENSION_BUFFER) + glBindImageTexture(resource->r.slot, resource->id, 0, GL_TRUE, + 0, GL_READ_WRITE, resource->format->internal_format); break; } } @@ -886,13 +903,16 @@ static bool gl_runner_draw(struct shader_runner *r, break; case RESOURCE_TYPE_UAV: - glBindImageTexture(resource->r.slot, resource->id, 0, GL_TRUE, - 0, GL_READ_WRITE, resource->format->internal_format); - break; - - case RESOURCE_TYPE_BUFFER_UAV: - glBindImageTexture(resource->r.slot, resource->tbo_id, 0, GL_TRUE, - 0, GL_READ_WRITE, resource->format->internal_format); + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) + { + glBindImageTexture(resource->r.slot, resource->tbo_id, 0, GL_TRUE, + 0, GL_READ_WRITE, resource->format->internal_format); + } + else + { + glBindImageTexture(resource->r.slot, resource->id, 0, GL_TRUE, + 0, GL_READ_WRITE, resource->format->internal_format); + } break; case RESOURCE_TYPE_VERTEX_BUFFER: @@ -973,8 +993,7 @@ static struct resource_readback *gl_runner_get_resource_readback(struct shader_r struct gl_resource *resource = gl_resource(res); struct resource_readback *rb; - if (resource->r.type != RESOURCE_TYPE_RENDER_TARGET && resource->r.type != RESOURCE_TYPE_UAV - && resource->r.type != RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.type != RESOURCE_TYPE_RENDER_TARGET && resource->r.type != RESOURCE_TYPE_UAV) fatal_error("Unhandled resource type %#x.\n", resource->r.type); rb = malloc(sizeof(*rb)); @@ -986,7 +1005,7 @@ static struct resource_readback *gl_runner_get_resource_readback(struct shader_r rb->row_pitch = rb->width * resource->r.texel_size; rb->data = malloc(rb->row_pitch * rb->height); - if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) { glBindBuffer(GL_TEXTURE_BUFFER, resource->id); glGetBufferSubData(GL_TEXTURE_BUFFER, 0, rb->row_pitch * rb->height, rb->data); diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index 4edf7f04..ca88dc99 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -264,14 +264,96 @@ static VkImageView create_2d_image_view(const struct vulkan_shader_runner *runne return view; } +static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_resource *resource, + const struct resource_params *params) +{ + VkImageUsageFlagBits usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkFormat format = vkd3d_get_vk_format(params->format); + VkDevice device = runner->device; + unsigned int buffer_offset = 0; + VkDeviceMemory staging_memory; + VkBuffer staging_buffer; + void *data; + + if (params->type == RESOURCE_TYPE_UAV) + { + layout = VK_IMAGE_LAYOUT_GENERAL; + usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + } + + resource->image = create_2d_image(runner, params->width, params->height, params->level_count, + usage, format, &resource->memory); + resource->image_view = create_2d_image_view(runner, resource->image, format); + + if (!params->data) + { + begin_command_buffer(runner); + transition_image_layout(runner, resource->image, + VK_IMAGE_LAYOUT_UNDEFINED, layout); + end_command_buffer(runner); + return; + } + + staging_buffer = create_buffer(runner, params->data_size, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_memory); + VK_CALL(vkMapMemory(device, staging_memory, 0, VK_WHOLE_SIZE, 0, &data)); + memcpy(data, params->data, params->data_size); + VK_CALL(vkUnmapMemory(device, staging_memory)); + + begin_command_buffer(runner); + + transition_image_layout(runner, resource->image, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + for (unsigned int level = 0; level < params->level_count; ++level) + { + unsigned int level_width = get_level_dimension(params->width, level); + unsigned int level_height = get_level_dimension(params->height, level); + VkBufferImageCopy region = {0}; + + region.bufferOffset = buffer_offset; + region.imageSubresource.mipLevel = level; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = level_width; + region.imageExtent.height = level_height; + region.imageExtent.depth = 1; + VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); + + buffer_offset += level_width * level_height * params->texel_size; + } + + transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout); + + end_command_buffer(runner); + + VK_CALL(vkFreeMemory(device, staging_memory, NULL)); + VK_CALL(vkDestroyBuffer(device, staging_buffer, NULL)); +} + +static void resource_init_buffer(struct vulkan_shader_runner *runner, struct vulkan_resource *resource, + const struct resource_params *params) +{ + VkFormat format = vkd3d_get_vk_format(params->format); + VkDevice device = runner->device; + void *data; + + resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory); + resource->buffer_view = create_buffer_view(runner, resource->buffer, format); + + VK_CALL(vkMapMemory(device, resource->memory, 0, VK_WHOLE_SIZE, 0, &data)); + memcpy(data, params->data, params->data_size); + VK_CALL(vkUnmapMemory(device, resource->memory)); +} + static struct resource *vulkan_runner_create_resource(struct shader_runner *r, const struct resource_params *params) { struct vulkan_shader_runner *runner = vulkan_shader_runner(r); - struct vulkan_resource *resource; VkDevice device = runner->device; - VkDeviceMemory staging_memory; - VkBuffer staging_buffer; VkFormat format; void *data; @@ -294,82 +376,14 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c break; case RESOURCE_TYPE_TEXTURE: - case RESOURCE_TYPE_UAV: - { - VkImageUsageFlagBits usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - unsigned int buffer_offset = 0; - - format = vkd3d_get_vk_format(params->format); - - if (params->type == RESOURCE_TYPE_UAV) - { - layout = VK_IMAGE_LAYOUT_GENERAL; - usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - } - - resource->image = create_2d_image(runner, params->width, params->height, params->level_count, - usage, format, &resource->memory); - resource->image_view = create_2d_image_view(runner, resource->image, format); - - if (!params->data) - { - begin_command_buffer(runner); - transition_image_layout(runner, resource->image, - VK_IMAGE_LAYOUT_UNDEFINED, layout); - end_command_buffer(runner); - break; - } - - staging_buffer = create_buffer(runner, params->data_size, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &staging_memory); - VK_CALL(vkMapMemory(device, staging_memory, 0, VK_WHOLE_SIZE, 0, &data)); - memcpy(data, params->data, params->data_size); - VK_CALL(vkUnmapMemory(device, staging_memory)); - - begin_command_buffer(runner); - - transition_image_layout(runner, resource->image, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - for (unsigned int level = 0; level < params->level_count; ++level) - { - unsigned int level_width = get_level_dimension(params->width, level); - unsigned int level_height = get_level_dimension(params->height, level); - VkBufferImageCopy region = {0}; - - region.bufferOffset = buffer_offset; - region.imageSubresource.mipLevel = level; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageExtent.width = level_width; - region.imageExtent.height = level_height; - region.imageExtent.depth = 1; - VK_CALL(vkCmdCopyBufferToImage(runner->cmd_buffer, staging_buffer, resource->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); - - buffer_offset += level_width * level_height * params->texel_size; - } - - transition_image_layout(runner, resource->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout); - - end_command_buffer(runner); - - VK_CALL(vkFreeMemory(device, staging_memory, NULL)); - VK_CALL(vkDestroyBuffer(device, staging_buffer, NULL)); + resource_init_2d(runner, resource, params); break; - } - case RESOURCE_TYPE_BUFFER_UAV: - format = vkd3d_get_vk_format(params->format); - - resource->buffer = create_buffer(runner, params->data_size, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &resource->memory); - resource->buffer_view = create_buffer_view(runner, resource->buffer, format); - - VK_CALL(vkMapMemory(device, resource->memory, 0, VK_WHOLE_SIZE, 0, &data)); - memcpy(data, params->data, params->data_size); - VK_CALL(vkUnmapMemory(device, resource->memory)); + case RESOURCE_TYPE_UAV: + if (params->dimension == RESOURCE_DIMENSION_BUFFER) + resource_init_buffer(runner, resource, params); + else + resource_init_2d(runner, resource, params); break; case RESOURCE_TYPE_VERTEX_BUFFER: @@ -510,16 +524,15 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: binding = &bindings[interface_info.binding_count++]; - if (resource->r.type == RESOURCE_TYPE_UAV || resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.type == RESOURCE_TYPE_UAV) binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; else binding->type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; binding->register_space = 0; binding->register_index = resource->r.slot; binding->shader_visibility = VKD3D_SHADER_VISIBILITY_ALL; - if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) binding->flags = VKD3D_SHADER_BINDING_FLAG_BUFFER; else binding->flags = VKD3D_SHADER_BINDING_FLAG_IMAGE; @@ -702,7 +715,6 @@ static VkPipeline create_graphics_pipeline(struct vulkan_shader_runner *runner, { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: break; case RESOURCE_TYPE_RENDER_TARGET: @@ -833,18 +845,22 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - case RESOURCE_TYPE_BUFFER_UAV: binding = &bindings[set_desc.bindingCount++]; resource->binding = binding_index++; binding->binding = resource->binding; if (resource->r.type == RESOURCE_TYPE_UAV) - binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - else if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) - binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + { + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) + binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + else + binding->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } else + { binding->descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + } binding->descriptorCount = 1; binding->stageFlags = VK_SHADER_STAGE_ALL; binding->pImmutableSamplers = NULL; @@ -908,34 +924,38 @@ static void bind_resources(struct vulkan_shader_runner *runner, VkPipelineBindPo { case RESOURCE_TYPE_TEXTURE: case RESOURCE_TYPE_UAV: - image_info.imageView = resource->image_view; - image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - write.dstSet = descriptor_set; - write.dstBinding = resource->binding; - write.dstArrayElement = 0; - write.descriptorCount = 1; - write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - write.pImageInfo = &image_info; - - if (resource->r.type == RESOURCE_TYPE_UAV) + if (resource->r.dimension == RESOURCE_DIMENSION_BUFFER) { - image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + assert(resource->r.type == RESOURCE_TYPE_UAV); + write.dstSet = descriptor_set; + write.dstBinding = resource->binding; + write.dstArrayElement = 0; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + write.pTexelBufferView = &resource->buffer_view; + + VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); } + else + { + image_info.imageView = resource->image_view; + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); - break; + write.dstSet = descriptor_set; + write.dstBinding = resource->binding; + write.dstArrayElement = 0; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + write.pImageInfo = &image_info; - case RESOURCE_TYPE_BUFFER_UAV: - write.dstSet = descriptor_set; - write.dstBinding = resource->binding; - write.dstArrayElement = 0; - write.descriptorCount = 1; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - write.pTexelBufferView = &resource->buffer_view; + if (resource->r.type == RESOURCE_TYPE_UAV) + { + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } - VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); + VK_CALL(vkUpdateDescriptorSets(runner->device, 1, &write, 0, NULL)); + } break; case RESOURCE_TYPE_VERTEX_BUFFER: @@ -1143,7 +1163,7 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad 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); - if (resource->r.type == RESOURCE_TYPE_BUFFER_UAV) + if (resource->r.type == RESOURCE_TYPE_UAV && resource->r.dimension == RESOURCE_DIMENSION_BUFFER) { void *data;