diff --git a/Makefile.am b/Makefile.am index bb7e7728..b6b8da71 100644 --- a/Makefile.am +++ b/Makefile.am @@ -212,6 +212,7 @@ vkd3d_shader_tests = \ tests/hlsl/return-implicit-conversion.shader_test \ tests/hlsl/return.shader_test \ tests/hlsl/round.shader_test \ + tests/hlsl/rt-array-index.shader_test \ tests/hlsl/rt-format-mismatch.shader_test \ tests/hlsl/rt-get-sample-info.shader_test \ tests/hlsl/sample-bias.shader_test \ diff --git a/tests/hlsl/rt-array-index.shader_test b/tests/hlsl/rt-array-index.shader_test new file mode 100644 index 00000000..5273679a --- /dev/null +++ b/tests/hlsl/rt-array-index.shader_test @@ -0,0 +1,50 @@ +[require] +shader model >= 4.0 +rt-vp-array-index + +[rtv 0] +format r32g32b32a32-float +size (2darray, 640, 480, 4) + +[vertex shader] +uint layer_offset; + +void main(float4 position : POSITION, + out float4 out_position : SV_POSITION, + out uint layer : SV_RenderTargetArrayIndex) +{ + out_position = position; + layer = layer_offset; +} + +[pixel shader] +uint layer_offset; +uint draw_id; + +float4 main(in float4 pos : SV_Position, + in uint layer : SV_RenderTargetArrayIndex) : SV_Target +{ + return float4(layer, draw_id, 0, 0); +} + +[test] +uniform 0 uint 0 +uniform 1 uint 0 +clear rtv 0 1.0 1.0 1.0 1.0 +todo(sm>=6 | glsl) draw quad +probe (320, 240, 0) rgba(0.0, 0.0, 0.0, 0.0) +probe (320, 240, 1) rgba(1.0, 1.0, 1.0, 1.0) + +uniform 0 uint 1 +uniform 1 uint 1 +clear rtv 0 1.0 1.0 1.0 1.0 +todo(sm>=6 | glsl) draw quad +probe (320, 240, 0) rgba(1.0, 1.0, 1.0, 1.0) +probe (320, 240, 1) rgba(1.0, 1.0, 0.0, 0.0) + +uniform 0 uint 3 +uniform 1 uint 2 +clear rtv 0 1.0 1.0 1.0 1.0 +todo(sm>=6 | glsl) draw quad +probe (320, 240, 0) rgba(1.0, 1.0, 1.0, 1.0) +probe (320, 240, 3) rgba(3.0, 2.0, 0.0, 0.0) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 5261b167..9de6b893 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -350,15 +350,16 @@ static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_t static const char *const shader_cap_strings[] = { - [SHADER_CAP_CLIP_PLANES] = "clip-planes", - [SHADER_CAP_DEPTH_BOUNDS] = "depth-bounds", - [SHADER_CAP_FLOAT64] = "float64", - [SHADER_CAP_FOG] = "fog", - [SHADER_CAP_GEOMETRY_SHADER] = "geometry-shader", - [SHADER_CAP_INT64] = "int64", - [SHADER_CAP_POINT_SIZE] = "point-size", - [SHADER_CAP_ROV] = "rov", - [SHADER_CAP_WAVE_OPS] = "wave-ops", + [SHADER_CAP_CLIP_PLANES] = "clip-planes", + [SHADER_CAP_DEPTH_BOUNDS] = "depth-bounds", + [SHADER_CAP_FLOAT64] = "float64", + [SHADER_CAP_FOG] = "fog", + [SHADER_CAP_GEOMETRY_SHADER] = "geometry-shader", + [SHADER_CAP_INT64] = "int64", + [SHADER_CAP_POINT_SIZE] = "point-size", + [SHADER_CAP_ROV] = "rov", + [SHADER_CAP_RT_VP_ARRAY_INDEX] = "rt-vp-array-index", + [SHADER_CAP_WAVE_OPS] = "wave-ops", }; static bool match_shader_cap_string(const char *line, enum shader_cap *cap) @@ -570,17 +571,20 @@ static void parse_resource_directive(struct resource_params *resource, const cha { resource->desc.dimension = RESOURCE_DIMENSION_BUFFER; resource->desc.height = 1; + resource->desc.depth = 1; } else if (sscanf(line, "( raw_buffer , %u ) ", &resource->desc.width) == 1) { resource->desc.dimension = RESOURCE_DIMENSION_BUFFER; resource->desc.height = 1; + resource->desc.depth = 1; resource->is_raw = true; } else if (sscanf(line, "( counter_buffer , %u ) ", &resource->desc.width) == 1) { resource->desc.dimension = RESOURCE_DIMENSION_BUFFER; resource->desc.height = 1; + resource->desc.depth = 1; resource->is_uav_counter = true; resource->stride = sizeof(uint32_t); resource->desc.texel_size = resource->stride; @@ -591,9 +595,16 @@ static void parse_resource_directive(struct resource_params *resource, const cha else if (sscanf(line, "( 2d , %u , %u ) ", &resource->desc.width, &resource->desc.height) == 2) { resource->desc.dimension = RESOURCE_DIMENSION_2D; + resource->desc.depth = 1; } else if (sscanf(line, "( 2dms , %u , %u , %u ) ", &resource->desc.sample_count, &resource->desc.width, &resource->desc.height) == 3) + { + resource->desc.dimension = RESOURCE_DIMENSION_2D; + resource->desc.depth = 1; + } + else if (sscanf(line, "( 2darray , %u , %u , %u ) ", &resource->desc.width, &resource->desc.height, + &resource->desc.depth) == 3) { resource->desc.dimension = RESOURCE_DIMENSION_2D; } @@ -642,6 +653,9 @@ static void parse_resource_directive(struct resource_params *resource, const cha if (rest == line) break; + if (resource->desc.depth > 1) + fatal_error("Upload not implemented for 2d arrays.\n"); + vkd3d_array_reserve((void **)&resource->data, &resource->data_capacity, resource->data_size + sizeof(u), 1); memcpy(resource->data + resource->data_size, &u, sizeof(u)); resource->data_size += sizeof(u); @@ -754,6 +768,7 @@ static void set_default_target(struct shader_runner *runner) params.desc.texel_size = 16; params.desc.width = RENDER_TARGET_WIDTH; params.desc.height = RENDER_TARGET_HEIGHT; + params.desc.depth = 1; params.desc.level_count = 1; set_resource(runner, ¶ms); @@ -1124,7 +1139,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) } else if (match_string(line, "probe", &line)) { - unsigned int left, top, right, bottom, ulps, slot; + unsigned int left, top, right, bottom, ulps, slot, array_layer = 0; struct resource_readback *rb; struct resource *resource; bool is_signed = false; @@ -1163,13 +1178,16 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) resource = shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, 0); } - rb = runner->ops->get_resource_readback(runner, resource); - if (sscanf(line, " ( %d , %d , %d , %d )%n", &left, &top, &right, &bottom, &len) == 4) { set_rect(&rect, left, top, right, bottom); line += len; } + else if (sscanf(line, " ( %u , %u , %u )%n", &left, &top, &array_layer, &len) == 3) + { + set_rect(&rect, left, top, left + 1, top + 1); + line += len; + } else if (sscanf(line, " ( %u , %u )%n", &left, &top, &len) == 2) { set_rect(&rect, left, top, left + 1, top + 1); @@ -1185,6 +1203,8 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) fatal_error("Malformed probe arguments '%s'.\n", line); } + rb = runner->ops->get_resource_readback(runner, resource, array_layer * resource->desc.level_count); + if (match_string(line, "rgbaui", &line)) { struct uvec4 v; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 786b2a5c..da594b46 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -95,7 +95,7 @@ struct resource_desc DXGI_FORMAT format; unsigned int texel_size; - unsigned int width, height; + unsigned int width, height, depth; unsigned int level_count; unsigned int sample_count; }; @@ -148,6 +148,7 @@ enum shader_cap SHADER_CAP_INT64, SHADER_CAP_POINT_SIZE, SHADER_CAP_ROV, + SHADER_CAP_RT_VP_ARRAY_INDEX, SHADER_CAP_WAVE_OPS, SHADER_CAP_COUNT, }; @@ -251,7 +252,8 @@ struct shader_runner_ops unsigned int instance_count); bool (*copy)(struct shader_runner *runner, struct resource *src, struct resource *dst); bool (*dispatch)(struct shader_runner *runner, unsigned int x, unsigned int y, unsigned int z); - struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, struct resource *resource); + struct resource_readback *(*get_resource_readback)(struct shader_runner *runner, + struct resource *resource, unsigned int sub_resource_idx); 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 a0769fe9..e5d24316 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -260,6 +260,7 @@ static bool get_format_support(ID3D11Device *device, enum DXGI_FORMAT format) static BOOL init_test_context(struct d3d11_shader_runner *runner) { D3D11_FEATURE_DATA_D3D11_OPTIONS2 options2 = {0}; + D3D11_FEATURE_DATA_D3D11_OPTIONS3 options3 = {0}; D3D11_FEATURE_DATA_DOUBLES doubles = {0}; unsigned int rt_width, rt_height; D3D11_RASTERIZER_DESC rs_desc; @@ -309,7 +310,12 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner) D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2)); ok(hr == S_OK, "Failed to check feature options2 support, hr %#lx.\n", hr); + hr = ID3D11Device_CheckFeatureSupport(runner->device, + D3D11_FEATURE_D3D11_OPTIONS3, &options3, sizeof(options3)); + ok(hr == S_OK, "Failed to check feature options3 support, hr %#lx.\n", hr); + runner->caps.shader_caps[SHADER_CAP_ROV] = options2.ROVsSupported; + runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX] = options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer; for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i) { runner->caps.format_caps[formats[i]] = get_format_support(runner->device, formats[i]); @@ -414,7 +420,7 @@ static bool init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re desc.Width = params->desc.width; desc.Height = params->desc.height; desc.MipLevels = params->desc.level_count; - desc.ArraySize = 1; + desc.ArraySize = params->desc.depth; desc.Format = params->desc.format; desc.SampleDesc.Count = max(params->desc.sample_count, 1); desc.Usage = D3D11_USAGE_DEFAULT; @@ -926,9 +932,11 @@ struct d3d11_resource_readback { struct resource_readback rb; ID3D11Resource *resource; + unsigned int sub_resource_idx; }; -static struct resource_readback *d3d11_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *d3d11_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct d3d11_shader_runner *runner = d3d11_shader_runner(r); struct d3d11_resource_readback *rb = malloc(sizeof(*rb)); @@ -990,7 +998,8 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade ID3D11DeviceContext_CopyStructureCount(runner->immediate_context, (ID3D11Buffer *)rb->resource, 0, resource->uav); else ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, src_resource); - hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc); + hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, + sub_resource_idx, D3D11_MAP_READ, 0, &map_desc); ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr); if (resolved_resource) @@ -1001,6 +1010,8 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade rb->rb.width = resource->r.desc.width; rb->rb.height = resource->r.desc.height; rb->rb.depth = 1; + rb->sub_resource_idx = sub_resource_idx; + return &rb->rb; } @@ -1009,7 +1020,7 @@ static void d3d11_runner_release_readback(struct shader_runner *r, struct resour struct d3d11_resource_readback *d3d11_rb = CONTAINING_RECORD(rb, struct d3d11_resource_readback, rb); struct d3d11_shader_runner *runner = d3d11_shader_runner(r); - ID3D11DeviceContext_Unmap(runner->immediate_context, d3d11_rb->resource, 0); + ID3D11DeviceContext_Unmap(runner->immediate_context, d3d11_rb->resource, d3d11_rb->sub_resource_idx); ID3D11Resource_Release(d3d11_rb->resource); free(d3d11_rb); } diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index f4f685bd..f5b08e5e 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -120,8 +120,9 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co if (params->desc.sample_count > 1 && params->desc.level_count > 1) fatal_error("Multisampled texture has multiple levels.\n"); - resource->resource = create_default_texture_(__FILE__, __LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, - params->desc.width, params->desc.height, 1, params->desc.level_count, params->desc.sample_count, + resource->resource = create_default_texture_(__FILE__, __LINE__, device, + D3D12_RESOURCE_DIMENSION_TEXTURE2D, params->desc.width, params->desc.height, + params->desc.depth, params->desc.level_count, params->desc.sample_count, params->desc.format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, initial_state); ID3D12Device_CreateRenderTargetView(device, resource->resource, NULL, get_cpu_rtv_handle(test_context, runner->rtv_heap, resource->r.desc.slot)); @@ -132,8 +133,8 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co runner->dsv_heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1); resource->resource = create_default_texture2d(device, params->desc.width, - params->desc.height, 1, params->desc.level_count, params->desc.format, - D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, initial_state); + params->desc.height, params->desc.depth, params->desc.level_count, + params->desc.format, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, initial_state); ID3D12Device_CreateDepthStencilView(device, resource->resource, NULL, get_cpu_dsv_handle(test_context, runner->dsv_heap, 0)); break; @@ -170,8 +171,8 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co fatal_error("Multisampled texture has multiple levels.\n"); resource->resource = create_default_texture_(__FILE__, __LINE__, device, - D3D12_RESOURCE_DIMENSION_TEXTURE2D, params->desc.width, params->desc.height, 1, - params->desc.level_count, params->desc.sample_count, params->desc.format, + D3D12_RESOURCE_DIMENSION_TEXTURE2D, params->desc.width, params->desc.height, + params->desc.depth, params->desc.level_count, params->desc.sample_count, params->desc.format, /* Multisampled textures must have ALLOW_RENDER_TARGET set. */ (params->desc.sample_count > 1) ? D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET : 0, initial_state); if (params->data) @@ -219,8 +220,8 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co else { resource->resource = create_default_texture2d(device, params->desc.width, - params->desc.height, 1, params->desc.level_count, params->desc.format, - D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, initial_state); + params->desc.height, params->desc.depth, params->desc.level_count, + params->desc.format, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, initial_state); if (params->data) { upload_texture_data_with_states(resource->resource, resource_data, params->desc.level_count, @@ -930,7 +931,8 @@ static bool d3d12_runner_copy(struct shader_runner *r, struct resource *src, str return true; } -static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *d3d12_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct d3d12_shader_runner *runner = d3d12_shader_runner(r); struct test_context *test_context = &runner->test_context; @@ -939,8 +941,8 @@ static struct resource_readback *d3d12_runner_get_resource_readback(struct shade D3D12_RESOURCE_STATES state; state = resource_get_state(res); - get_resource_readback_with_command_list_and_states(resource->resource, 0, rb, - test_context->queue, test_context->list, state, state); + get_resource_readback_with_command_list_and_states(resource->resource, + sub_resource_idx, rb, test_context->queue, test_context->list, state, state); reset_command_list(test_context->list, test_context->allocator); return &rb->rb; @@ -1033,6 +1035,8 @@ static void d3d12_runner_init_caps(struct d3d12_shader_runner *runner, runner->caps.shader_caps[SHADER_CAP_GEOMETRY_SHADER] = true; runner->caps.shader_caps[SHADER_CAP_INT64] = options1.Int64ShaderOps; runner->caps.shader_caps[SHADER_CAP_ROV] = options.ROVsSupported; + runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX] + = options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation; runner->caps.shader_caps[SHADER_CAP_WAVE_OPS] = options1.WaveOps; runner->caps.tag_count = 0; diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 4e148ad0..67280b7c 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -584,7 +584,8 @@ struct d3d9_resource_readback IDirect3DSurface9 *surface; }; -static struct resource_readback *d3d9_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *d3d9_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct d3d9_shader_runner *runner = d3d9_shader_runner(r); struct d3d9_resource_readback *rb = malloc(sizeof(*rb)); @@ -594,6 +595,8 @@ static struct resource_readback *d3d9_runner_get_resource_readback(struct shader HRESULT hr; assert(resource->r.desc.type == RESOURCE_TYPE_RENDER_TARGET); + if (sub_resource_idx) + fatal_error("Unsupported sub-resource index %u.\n", sub_resource_idx); hr = IDirect3DSurface9_GetDesc(resource->surface, &desc); ok(hr == D3D_OK, "Failed to get surface desc, hr %#lx.\n", hr); diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 07cb538f..83e659b3 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -58,6 +58,7 @@ struct gl_resource const struct format_info *format; GLuint id, tbo_id; + GLenum target; }; static struct gl_resource *gl_resource(struct resource *r) @@ -97,20 +98,30 @@ static void debug_output(GLenum source, GLenum type, GLuint id, GLenum severity, trace("%.*s\n", length, message); } -static bool check_gl_extension(const char *extension, GLint extension_count) +static bool check_extension(GLenum name, const char *extension, GLint extension_count) { for (GLint i = 0; i < extension_count; ++i) { - if (!strcmp(extension, (const char *)glGetStringi(GL_EXTENSIONS, i))) + if (!strcmp(extension, (const char *)glGetStringi(name, i))) return true; } return false; } +static bool check_gl_extension(const char *extension, GLint extension_count) +{ + return check_extension(GL_EXTENSIONS, extension, extension_count); +} + +static bool check_spirv_extension(const char *extension, GLint extension_count) +{ + return check_extension(GL_SPIR_V_EXTENSIONS, extension, extension_count); +} + static bool check_gl_extensions(struct gl_runner *runner) { - GLint count; + GLint count, spirv_count = 0; static const char *required_extensions[] = { @@ -126,8 +137,14 @@ static bool check_gl_extensions(struct gl_runner *runner) glGetIntegerv(GL_NUM_EXTENSIONS, &count); - if (runner->language == SPIR_V && !check_gl_extension("GL_ARB_gl_spirv", count)) - return false; + if (runner->language == SPIR_V) + { + if (!check_gl_extension("GL_ARB_gl_spirv", count)) + return false; + + if (check_gl_extension("GL_ARB_spirv_extensions", count)) + glGetIntegerv(GL_NUM_SPIR_V_EXTENSIONS, &spirv_count); + } for (unsigned int i = 0; i < ARRAY_SIZE(required_extensions); ++i) { @@ -139,6 +156,9 @@ static bool check_gl_extensions(struct gl_runner *runner) runner->caps.shader_caps[SHADER_CAP_FLOAT64] = true; if (check_gl_extension("GL_ARB_gpu_shader_int64", count)) runner->caps.shader_caps[SHADER_CAP_INT64] = true; + if (check_gl_extension("GL_ARB_shader_viewport_layer_array", count) && (runner->language == GLSL + || check_spirv_extension("SPV_EXT_shader_viewport_index_layer", spirv_count))) + runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX] = true; if (check_gl_extension("GL_EXT_depth_bounds_test", count)) runner->caps.shader_caps[SHADER_CAP_DEPTH_BOUNDS] = true; @@ -421,8 +441,16 @@ static void gl_runner_cleanup(struct gl_runner *runner) static bool init_resource_2d(struct gl_resource *resource, const struct resource_params *params) { - GLenum target = params->desc.sample_count > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; unsigned int offset, w, h, i; + GLenum target; + + if (params->desc.sample_count > 1) + target = GL_TEXTURE_2D_MULTISAMPLE; + else if (params->desc.depth > 1) + target = GL_TEXTURE_2D_ARRAY; + else + target = GL_TEXTURE_2D; + resource->target = target; resource->format = get_format_info(params->desc.format, params->is_shadow); @@ -447,8 +475,12 @@ static bool init_resource_2d(struct gl_resource *resource, const struct resource } else { - glTexStorage2D(target, params->desc.level_count, - resource->format->internal_format, params->desc.width, params->desc.height); + if (params->desc.depth > 1) + glTexStorage3D(target, params->desc.level_count, resource->format->internal_format, + params->desc.width, params->desc.height, params->desc.depth); + else + glTexStorage2D(target, params->desc.level_count, resource->format->internal_format, + params->desc.width, params->desc.height); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); } @@ -469,15 +501,18 @@ static bool init_resource_2d(struct gl_resource *resource, const struct resource static void init_resource_buffer(struct gl_resource *resource, const struct resource_params *params) { + GLenum target = GL_TEXTURE_BUFFER; + resource->format = get_format_info(params->desc.format, false); + resource->target = target; glGenBuffers(1, &resource->id); - glBindBuffer(GL_TEXTURE_BUFFER, resource->id); - glBufferData(GL_TEXTURE_BUFFER, params->data_size, params->data, GL_STATIC_DRAW); + glBindBuffer(target, resource->id); + glBufferData(target, 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); + glBindTexture(target, resource->tbo_id); + glTexBuffer(target, resource->format->internal_format, resource->id); } static struct resource *gl_runner_create_resource(struct shader_runner *r, const struct resource_params *params) @@ -549,6 +584,7 @@ static bool compile_shader(struct gl_runner *runner, enum shader_type shader_typ struct vkd3d_shader_scan_hull_shader_tessellation_info tessellation_info; struct vkd3d_shader_spirv_domain_shader_target_info domain_info; struct vkd3d_shader_combined_resource_sampler *sampler; + enum vkd3d_shader_spirv_extension spirv_extensions[1]; struct vkd3d_shader_resource_binding *binding; struct vkd3d_shader_parameter parameters[1]; unsigned int count, i; @@ -620,6 +656,10 @@ static bool compile_shader(struct gl_runner *runner, enum shader_type shader_typ info.next = &spirv_info; spirv_info.next = &interface_info; spirv_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5; + spirv_info.extensions = spirv_extensions; + spirv_info.extension_count = 0; + if (runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX]) + spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER; } else { @@ -1159,11 +1199,9 @@ static bool gl_runner_draw(struct shader_runner *r, glActiveTexture(GL_TEXTURE0 + s->binding.binding); if (resource->desc.dimension == RESOURCE_DIMENSION_BUFFER) - glBindTexture(GL_TEXTURE_BUFFER, gl_resource(resource)->tbo_id); - else if (resource->desc.sample_count > 1) - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, gl_resource(resource)->id); + glBindTexture(gl_resource(resource)->target, gl_resource(resource)->tbo_id); else - glBindTexture(GL_TEXTURE_2D, gl_resource(resource)->id); + glBindTexture(gl_resource(resource)->target, gl_resource(resource)->id); if (s->sampler_index == VKD3D_SHADER_DUMMY_SAMPLER_INDEX) continue; @@ -1306,19 +1344,16 @@ static bool gl_runner_copy(struct shader_runner *r, struct resource *src, struct { struct gl_resource *s = gl_resource(src); struct gl_resource *d = gl_resource(dst); - GLenum target = GL_TEXTURE_2D; unsigned int l, w, h; - if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER) + if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER || src->desc.depth > 1) return false; - if (src->desc.sample_count > 1) - target = GL_TEXTURE_2D_MULTISAMPLE; for (l = 0; l < src->desc.level_count; ++l) { w = get_level_dimension(src->desc.width, l); h = get_level_dimension(src->desc.height, l); - glCopyImageSubData(s->id, target, l, 0, 0, 0, d->id, target, l, 0, 0, 0, w, h, 1); + glCopyImageSubData(s->id, s->target, l, 0, 0, 0, d->id, d->target, l, 0, 0, 0, w, h, 1); } return true; @@ -1329,11 +1364,14 @@ struct gl_resource_readback struct resource_readback rb; }; -static struct resource_readback *gl_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *gl_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct gl_resource *resource = gl_resource(res); struct gl_runner *runner = gl_runner(r); struct resource_readback *rb; + unsigned int layer, level; + size_t slice_pitch; if (resource->r.desc.type != RESOURCE_TYPE_RENDER_TARGET && resource->r.desc.type != RESOURCE_TYPE_DEPTH_STENCIL && resource->r.desc.type != RESOURCE_TYPE_UAV) @@ -1346,12 +1384,16 @@ static struct resource_readback *gl_runner_get_resource_readback(struct shader_r rb->depth = 1; rb->row_pitch = rb->width * resource->r.desc.texel_size; - rb->data = malloc(rb->row_pitch * rb->height); + slice_pitch = rb->row_pitch * rb->height; + rb->data = calloc(slice_pitch, resource->r.desc.depth); + + level = sub_resource_idx % resource->r.desc.level_count; + layer = sub_resource_idx / resource->r.desc.level_count; if (resource->r.desc.dimension == RESOURCE_DIMENSION_BUFFER) { - glBindBuffer(GL_TEXTURE_BUFFER, resource->id); - glGetBufferSubData(GL_TEXTURE_BUFFER, 0, rb->row_pitch * rb->height, rb->data); + glBindBuffer(resource->target, resource->id); + glGetBufferSubData(resource->target, 0, slice_pitch, rb->data); } else if (resource->r.desc.sample_count > 1) { @@ -1385,8 +1427,10 @@ static struct resource_readback *gl_runner_get_resource_readback(struct shader_r } else { - glBindTexture(GL_TEXTURE_2D, resource->id); - glGetTexImage(GL_TEXTURE_2D, 0, resource->format->format, resource->format->type, rb->data); + glBindTexture(resource->target, resource->id); + glGetTexImage(resource->target, level, resource->format->format, resource->format->type, rb->data); + if (layer) + memcpy(rb->data, (const uint8_t *)rb->data + layer * slice_pitch, slice_pitch); } return rb; diff --git a/tests/shader_runner_metal.m b/tests/shader_runner_metal.m index 233a8424..5ecd24cf 100644 --- a/tests/shader_runner_metal.m +++ b/tests/shader_runner_metal.m @@ -200,10 +200,13 @@ static void init_resource_texture(struct metal_runner *runner, desc = [[MTLTextureDescriptor alloc] init]; if (params->desc.sample_count > 1) desc.textureType = MTLTextureType2DMultisample; + else if (params->desc.depth > 1) + desc.textureType = MTLTextureType2DArray; desc.pixelFormat = get_metal_pixel_format(params->desc.format); ok(desc.pixelFormat != MTLPixelFormatInvalid, "Unhandled pixel format %#x.\n", params->desc.format); desc.width = params->desc.width; desc.height = params->desc.height; + desc.arrayLength = params->desc.depth; desc.mipmapLevelCount = params->desc.level_count; desc.sampleCount = max(params->desc.sample_count, 1); desc.storageMode = MTLStorageModePrivate; @@ -572,13 +575,15 @@ static bool metal_runner_copy(struct shader_runner *r, struct resource *src, str return false; } -static struct resource_readback *metal_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *metal_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct metal_resource *resource = metal_resource(res); struct metal_runner *runner = metal_runner(r); id command_buffer; struct metal_resource_readback *rb; id blit; + unsigned int layer, level; if (resource->r.desc.dimension != RESOURCE_DIMENSION_2D) fatal_error("Unhandled resource dimension %#x.\n", resource->r.desc.dimension); @@ -593,14 +598,17 @@ static struct resource_readback *metal_runner_get_resource_readback(struct shade rb->buffer = [runner->device newBufferWithLength:rb->rb.row_pitch * rb->rb.height options:DEFAULT_BUFFER_RESOURCE_OPTIONS]; + level = sub_resource_idx % resource->r.desc.level_count; + layer = sub_resource_idx / resource->r.desc.level_count; + @autoreleasepool { command_buffer = [runner->queue commandBuffer]; blit = [command_buffer blitCommandEncoder]; [blit copyFromTexture:resource->texture - sourceSlice:0 - sourceLevel:0 + sourceSlice:layer + sourceLevel:level sourceOrigin:MTLOriginMake(0, 0, 0) sourceSize:MTLSizeMake(rb->rb.width, rb->rb.height, rb->rb.depth) toBuffer:rb->buffer diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index 42ddb5f4..de2c487c 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -93,6 +93,7 @@ static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_ const struct vulkan_test_context *context = &runner->context; VkFormat format = vkd3d_get_vk_format(params->desc.format); const struct resource_desc *desc = ¶ms->desc; + uint32_t layer_count = desc->depth; VkDevice device = context->device; unsigned int buffer_offset = 0; VkDeviceMemory staging_memory; @@ -105,15 +106,16 @@ static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_ usage |= VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } - resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count, desc->sample_count, - usage, format, &resource->memory); - resource->image_view = create_vulkan_2d_image_view(context, resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT); + resource->image = create_vulkan_2d_image(context, desc->width, desc->height, + desc->level_count, desc->depth, desc->sample_count, usage, format, &resource->memory); + resource->image_view = create_vulkan_2d_image_view(context, + resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT, layer_count); if (!params->data) { begin_command_buffer(context); transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, layout); + 0, layer_count, VK_IMAGE_LAYOUT_UNDEFINED, layout); end_command_buffer(context); return; } @@ -126,8 +128,8 @@ static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_ begin_command_buffer(context); - transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, 0, + layer_count, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); for (unsigned int level = 0; level < params->desc.level_count; ++level) { @@ -148,7 +150,8 @@ static void resource_init_2d(struct vulkan_shader_runner *runner, struct vulkan_ buffer_offset += level_width * level_height * params->desc.texel_size; } - transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout); + transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, + 0, layer_count, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, layout); end_command_buffer(context); @@ -188,6 +191,7 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c struct vulkan_shader_runner *runner = vulkan_shader_runner(r); const struct vulkan_test_context *context = &runner->context; const struct resource_desc *desc = ¶ms->desc; + unsigned int layer_count = desc->depth; VkDevice device = context->device; struct vulkan_resource *resource; VkFormat format; @@ -201,29 +205,30 @@ static struct resource *vulkan_runner_create_resource(struct shader_runner *r, c case RESOURCE_TYPE_RENDER_TARGET: format = vkd3d_get_vk_format(params->desc.format); - resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count, - desc->sample_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - format, &resource->memory); + resource->image = create_vulkan_2d_image(context, desc->width, + desc->height, desc->level_count, desc->depth, desc->sample_count, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, format, &resource->memory); resource->image_view = create_vulkan_2d_image_view(context, - resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT); + resource->image, format, VK_IMAGE_ASPECT_COLOR_BIT, layer_count); begin_command_buffer(context); - transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_COLOR_BIT, 0, + layer_count, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); end_command_buffer(context); break; case RESOURCE_TYPE_DEPTH_STENCIL: format = vkd3d_get_vk_format(params->desc.format); - resource->image = create_vulkan_2d_image(context, desc->width, desc->height, desc->level_count, - desc->sample_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + resource->image = create_vulkan_2d_image(context, desc->width, + desc->height, desc->level_count, desc->depth, desc->sample_count, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, format, &resource->memory); resource->image_view = create_vulkan_2d_image_view(context, - resource->image, format, VK_IMAGE_ASPECT_DEPTH_BIT); + resource->image, format, VK_IMAGE_ASPECT_DEPTH_BIT, layer_count); begin_command_buffer(context); - transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_DEPTH_BIT, + transition_image_layout(context, resource->image, VK_IMAGE_ASPECT_DEPTH_BIT, 0, layer_count, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); end_command_buffer(context); break; @@ -339,7 +344,7 @@ static bool compile_d3d_code(struct vulkan_shader_runner *runner, struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; struct vkd3d_shader_resource_binding bindings[MAX_RESOURCES + MAX_SAMPLERS]; struct vkd3d_shader_push_constant_buffer push_constants; - enum vkd3d_shader_spirv_extension spirv_extensions[2]; + enum vkd3d_shader_spirv_extension spirv_extensions[3]; struct vkd3d_shader_varying_map varying_map[12]; struct vkd3d_shader_resource_binding *binding; struct vkd3d_shader_compile_option options[2]; @@ -384,6 +389,8 @@ static bool compile_d3d_code(struct vulkan_shader_runner *runner, if (runner->caps.shader_caps[SHADER_CAP_ROV]) spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK; + if (runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX]) + spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER; if (runner->demote_to_helper_invocation) spirv_extensions[spirv_info.extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION; @@ -1083,6 +1090,7 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn unsigned int i, color_ref_count = 0, view_count = 0; VkSubpassDescription subpass_desc = {0}; VkImageView views[MAX_RESOURCES]; + unsigned int layer_count = ~0u; VkImageLayout layout; bool is_ds; @@ -1126,6 +1134,8 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn runner->rt_size.width = resource->r.desc.width; if (resource->r.desc.height < runner->rt_size.height) runner->rt_size.height = resource->r.desc.height; + if (resource->r.desc.depth < layer_count) + layer_count = resource->r.desc.depth; views[view_count++] = resource->image_view; } @@ -1146,7 +1156,7 @@ static void create_render_pass_and_framebuffer(struct vulkan_shader_runner *runn fb_desc.pAttachments = views; fb_desc.width = runner->rt_size.width; fb_desc.height = runner->rt_size.height; - fb_desc.layers = 1; + fb_desc.layers = layer_count; VK_CALL(vkCreateFramebuffer(context->device, &fb_desc, NULL, fb)); } @@ -1265,7 +1275,7 @@ static void vulkan_runner_clear(struct shader_runner *r, struct resource *res, c fb_desc.pAttachments = &resource->image_view; fb_desc.width = width; fb_desc.height = height; - fb_desc.layers = 1; + fb_desc.layers = resource->r.desc.depth; VK_CALL(vkCreateFramebuffer(device, &fb_desc, NULL, &fb)); begin_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -1367,7 +1377,7 @@ static bool vulkan_runner_copy(struct shader_runner *r, struct resource *src, st VkImageCopy vk_image_copy; unsigned int l; - if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER) + if (src->desc.dimension == RESOURCE_DIMENSION_BUFFER || src->desc.depth > 1) return false; if (src->desc.type == RESOURCE_TYPE_DEPTH_STENCIL) @@ -1377,8 +1387,8 @@ static bool vulkan_runner_copy(struct shader_runner *r, struct resource *src, st dst_layout = resource_get_layout(dst); begin_command_buffer(context); - transition_image_layout(context, s->image, aspect_mask, src_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - transition_image_layout(context, d->image, aspect_mask, + transition_image_layout(context, s->image, aspect_mask, 0, 1, src_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + transition_image_layout(context, d->image, aspect_mask, 0, 1, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vk_image_copy.srcSubresource = (VkImageSubresourceLayers){.aspectMask = aspect_mask, .layerCount = 1}; @@ -1398,8 +1408,8 @@ static bool vulkan_runner_copy(struct shader_runner *r, struct resource *src, st d->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vk_image_copy)); } - transition_image_layout(context, d->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_layout); - transition_image_layout(context, s->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_layout); + transition_image_layout(context, d->image, aspect_mask, 0, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_layout); + transition_image_layout(context, s->image, aspect_mask, 0, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_layout); end_command_buffer(context); return true; @@ -1412,7 +1422,8 @@ struct vulkan_resource_readback VkBuffer buffer; }; -static struct resource_readback *vulkan_runner_get_resource_readback(struct shader_runner *r, struct resource *res) +static struct resource_readback *vulkan_runner_get_resource_readback(struct shader_runner *r, + struct resource *res, unsigned int sub_resource_idx) { struct vulkan_shader_runner *runner = vulkan_shader_runner(r); const struct vulkan_test_context *context = &runner->context; @@ -1421,6 +1432,7 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad VkDevice device = context->device; VkImageAspectFlags aspect_mask; VkBufferImageCopy region = {0}; + unsigned int layer, level; VkImageLayout layout; rb->rb.width = resource->r.desc.width; @@ -1447,15 +1459,20 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad VkImage resolved_image = VK_NULL_HANDLE; VkDeviceMemory resolved_memory; + level = sub_resource_idx % resource->r.desc.level_count; + layer = sub_resource_idx / resource->r.desc.level_count; aspect_mask = (resource->r.desc.type == RESOURCE_TYPE_DEPTH_STENCIL) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; layout = resource_get_layout(res); begin_command_buffer(context); - transition_image_layout(context, resource->image, aspect_mask, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + transition_image_layout(context, resource->image, aspect_mask, + layer, 1, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); region.imageSubresource.aspectMask = aspect_mask; + region.imageSubresource.mipLevel = level; + region.imageSubresource.baseArrayLayer = layer; region.imageSubresource.layerCount = 1; region.imageExtent.width = resource->r.desc.width; region.imageExtent.height = resource->r.desc.height; @@ -1475,16 +1492,16 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad resolved_desc.sample_count = 1; resolved_image = create_vulkan_2d_image(context, resolved_desc.width, resolved_desc.height, - resolved_desc.level_count, resolved_desc.sample_count, + resolved_desc.level_count, resolved_desc.depth, resolved_desc.sample_count, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, vkd3d_get_vk_format(resource->r.desc.format), &resolved_memory); - transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT, layer, + 1, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VK_CALL(vkCmdResolveImage(context->cmd_buffer, resource->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolved_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve_region)); - transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + transition_image_layout(context, resolved_image, VK_IMAGE_ASPECT_COLOR_BIT, layer, + 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VK_CALL(vkCmdCopyImageToBuffer(context->cmd_buffer, resolved_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion)); } @@ -1494,7 +1511,8 @@ static struct resource_readback *vulkan_runner_get_resource_readback(struct shad VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, rb->buffer, 1, ®ion)); } - transition_image_layout(context, resource->image, aspect_mask, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout); + transition_image_layout(context, resource->image, aspect_mask, + layer, 1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, layout); end_command_buffer(context); @@ -1553,6 +1571,7 @@ static bool check_device_extensions(struct vulkan_shader_runner *runner, { {VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME}, {VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME}, + {VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME}, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, true}, {VK_KHR_MAINTENANCE1_EXTENSION_NAME, true}, {VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME}, @@ -1574,6 +1593,8 @@ static bool check_device_extensions(struct vulkan_shader_runner *runner, enabled_extensions->names[enabled_extensions->count++] = name; if (!strcmp(name, VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME)) runner->caps.shader_caps[SHADER_CAP_ROV] = true; + if (!strcmp(name, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME)) + runner->caps.shader_caps[SHADER_CAP_RT_VP_ARRAY_INDEX] = true; if (!strcmp(name, VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)) runner->demote_to_helper_invocation = true; if (!strcmp(name, VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) diff --git a/tests/vulkan_utils.h b/tests/vulkan_utils.h index 4f45bc20..c64dd2ea 100644 --- a/tests/vulkan_utils.h +++ b/tests/vulkan_utils.h @@ -73,7 +73,8 @@ static inline void end_command_buffer(const struct vulkan_test_context *context) } static inline void transition_image_layout(const struct vulkan_test_context *context, - VkImage image, VkImageAspectFlags aspect_mask, VkImageLayout src_layout, VkImageLayout dst_layout) + VkImage image, VkImageAspectFlags aspect_mask, uint32_t base_layer, uint32_t layer_count, + VkImageLayout src_layout, VkImageLayout dst_layout) { VkImageMemoryBarrier barrier = {.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; @@ -87,8 +88,8 @@ static inline void transition_image_layout(const struct vulkan_test_context *con barrier.subresourceRange.aspectMask = aspect_mask; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.baseArrayLayer = base_layer; + barrier.subresourceRange.layerCount = layer_count; VK_CALL(vkCmdPipelineBarrier(context->cmd_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier)); @@ -166,8 +167,9 @@ static inline VkBufferView create_vulkan_buffer_view(const struct vulkan_test_co return view; } -static inline VkImage create_vulkan_2d_image(const struct vulkan_test_context *context, uint32_t width, uint32_t height, - uint32_t level_count, uint32_t sample_count, VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory) +static inline VkImage create_vulkan_2d_image(const struct vulkan_test_context *context, unsigned int width, + unsigned int height, unsigned int level_count, unsigned int layer_count, unsigned int sample_count, + VkImageUsageFlags usage, VkFormat format, VkDeviceMemory *memory) { VkImageCreateInfo image_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; VkMemoryRequirements memory_reqs; @@ -179,7 +181,7 @@ static inline VkImage create_vulkan_2d_image(const struct vulkan_test_context *c image_info.extent.height = height; image_info.extent.depth = 1; image_info.mipLevels = level_count; - image_info.arrayLayers = 1; + image_info.arrayLayers = layer_count; image_info.samples = max(sample_count, 1); image_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_info.usage = usage; @@ -196,13 +198,13 @@ static inline VkImage create_vulkan_2d_image(const struct vulkan_test_context *c } static inline VkImageView create_vulkan_2d_image_view(const struct vulkan_test_context *context, - VkImage image, VkFormat format, VkImageAspectFlags aspect_mask) + VkImage image, VkFormat format, VkImageAspectFlags aspect_mask, unsigned int layer_count) { VkImageViewCreateInfo view_info = {.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; VkImageView view; view_info.image = image; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.viewType = (layer_count > 1) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D; view_info.format = format; view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; @@ -212,7 +214,7 @@ static inline VkImageView create_vulkan_2d_image_view(const struct vulkan_test_c view_info.subresourceRange.baseMipLevel = 0; view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; view_info.subresourceRange.baseArrayLayer = 0; - view_info.subresourceRange.layerCount = 1; + view_info.subresourceRange.layerCount = layer_count; VK_CALL(vkCreateImageView(context->device, &view_info, NULL, &view)); return view;