-- v16: vkd3d-shader/dxil: Implement DX intrinsic RenderTargetGetSampleCount. vkd3d-shader/dxil: Implement DX intrinsics Texture2DMSGetSamplePosition and RenderTargetGetSamplePosition. tests/hlsl: Add tests for GetSamplePosition() and GetSampleCount().
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 58 +++++++++++++++++++++++ tests/hlsl/get-sample-pos.shader_test | 2 +- tests/hlsl/rt-get-sample-info.shader_test | 4 +- 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index b5a61d99d..8fa632d73 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -401,6 +401,8 @@ enum dx_intrinsic_opcode DX_GET_DIMENSIONS = 72, DX_TEXTURE_GATHER = 73, DX_TEXTURE_GATHER_CMP = 74, + DX_TEX2DMS_GET_SAMPLE_POS = 75, + DX_RT_GET_SAMPLE_POS = 76, DX_ATOMIC_BINOP = 78, DX_ATOMIC_CMP_XCHG = 79, DX_BARRIER = 80, @@ -2573,6 +2575,26 @@ static bool sm6_value_validate_is_texture_handle(const struct sm6_value *value, return true; }
+static bool sm6_value_validate_is_texture_2dms_handle(const struct sm6_value *value, enum dx_intrinsic_opcode op, + struct sm6_parser *sm6) +{ + enum dxil_resource_kind kind; + + if (!sm6_value_validate_is_handle(value, sm6)) + return false; + + kind = value->u.handle.d->kind; + if (!resource_kind_is_multisampled(kind)) + { + WARN("Resource kind %u for op %u is not a 2DMS texture.\n", kind, op); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE, + "Resource kind %u for texture operation %u is not a 2DMS texture.", kind, op); + return false; + } + + return true; +} + static bool sm6_value_validate_is_sampler_handle(const struct sm6_value *value, enum dx_intrinsic_opcode op, struct sm6_parser *sm6) { @@ -4993,6 +5015,40 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr dst_param->reg = resource->u.handle.reg; }
+static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + const struct sm6_value *resource = NULL; + + if (op == DX_TEX2DMS_GET_SAMPLE_POS) + { + resource = operands[0]; + if (!sm6_value_validate_is_texture_2dms_handle(resource, op, sm6)) + return; + } + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SAMPLE_POS); + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; + if (op == DX_TEX2DMS_GET_SAMPLE_POS) + { + src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + src_param_init_from_value(&src_params[1], operands[1]); + } + else + { + src_param_init_vector(&src_params[0], 2); + vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); + src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_from_value(&src_params[1], operands[0]); + } + + instruction_dst_param_init_ssa_vector(ins, 2, sm6); +} + static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) { return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); @@ -5439,6 +5495,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_RT_GET_SAMPLE_POS ] = {"o", "i", sm6_parser_emit_dx_get_sample_pos}, [DX_SAMPLE ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, [DX_SAMPLE_B ] = {"o", "HHffffiiiff", sm6_parser_emit_dx_sample}, [DX_SAMPLE_C ] = {"o", "HHffffiiiff", sm6_parser_emit_dx_sample}, @@ -5451,6 +5508,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_TEX2DMS_GET_SAMPLE_POS ] = {"o", "Hi", sm6_parser_emit_dx_get_sample_pos}, [DX_TEXTURE_GATHER ] = {"o", "HHffffiic", sm6_parser_emit_dx_texture_gather}, [DX_TEXTURE_GATHER_CMP ] = {"o", "HHffffiicf", sm6_parser_emit_dx_texture_gather}, [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, diff --git a/tests/hlsl/get-sample-pos.shader_test b/tests/hlsl/get-sample-pos.shader_test index 5c4743d47..1357f4031 100644 --- a/tests/hlsl/get-sample-pos.shader_test +++ b/tests/hlsl/get-sample-pos.shader_test @@ -16,5 +16,5 @@ float4 main() : sv_target }
[test] -todo draw quad +todo(sm<6 | glsl) draw quad probe all rgba (-0.125, -0.375, 0.375, -0.125) diff --git a/tests/hlsl/rt-get-sample-info.shader_test b/tests/hlsl/rt-get-sample-info.shader_test index f0a0e67a5..d26b4db8f 100644 --- a/tests/hlsl/rt-get-sample-info.shader_test +++ b/tests/hlsl/rt-get-sample-info.shader_test @@ -28,8 +28,8 @@ float4 main() : sv_target
[test] uniform 0 uint 0 -todo draw quad +todo(sm<6 | glsl) draw quad probe all rgba (-0.125, -0.375, 0.375, -0.125) uniform 0 uint 2 -todo draw quad +todo(sm<6 | glsl) draw quad probe all rgba (-0.375, 0.125, 0.125, 0.375)
From: Conor McCarthy cmccarthy@codeweavers.com
--- Makefile.am | 2 + tests/d3d12_test_utils.h | 10 ++--- tests/hlsl/get-sample-pos.shader_test | 20 +++++++++ tests/hlsl/rt-get-sample-info.shader_test | 35 ++++++++++++++++ tests/shader_runner.c | 16 ++++++-- tests/shader_runner.h | 4 ++ tests/shader_runner_d3d11.c | 30 +++++++++++++- tests/shader_runner_d3d12.c | 50 +++++++++++++++++------ tests/shader_runner_gl.c | 9 ++++ tests/shader_runner_vulkan.c | 2 + 10 files changed, 156 insertions(+), 22 deletions(-) create mode 100644 tests/hlsl/get-sample-pos.shader_test create mode 100644 tests/hlsl/rt-get-sample-info.shader_test
diff --git a/Makefile.am b/Makefile.am index 68e8642e0..7b6fb8914 100644 --- a/Makefile.am +++ b/Makefile.am @@ -112,6 +112,7 @@ vkd3d_shader_tests = \ tests/hlsl/fwidth.shader_test \ tests/hlsl/gather-offset.shader_test \ tests/hlsl/gather.shader_test \ + tests/hlsl/get-sample-pos.shader_test \ tests/hlsl/getdimensions.shader_test \ tests/hlsl/half.shader_test \ tests/hlsl/hard-copy-prop.shader_test \ @@ -167,6 +168,7 @@ vkd3d_shader_tests = \ tests/hlsl/return-implicit-conversion.shader_test \ tests/hlsl/return.shader_test \ tests/hlsl/round.shader_test \ + tests/hlsl/rt-get-sample-info.shader_test \ tests/hlsl/sample-bias.shader_test \ tests/hlsl/sample-cmp.shader_test \ tests/hlsl/sample-grad.shader_test \ diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index 4fe6fa716..85747297c 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -582,8 +582,8 @@ static inline ID3D12Resource *create_default_buffer_(unsigned int line, ID3D12De
static ID3D12Resource *create_default_texture_(unsigned int line, ID3D12Device *device, D3D12_RESOURCE_DIMENSION dimension, unsigned int width, unsigned int height, - unsigned int depth_or_array_size, unsigned int miplevel_count, DXGI_FORMAT format, - D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) + unsigned int depth_or_array_size, unsigned int miplevel_count, unsigned int sample_count, + DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { D3D12_HEAP_PROPERTIES heap_properties; D3D12_RESOURCE_DESC resource_desc; @@ -602,7 +602,7 @@ static ID3D12Resource *create_default_texture_(unsigned int line, ID3D12Device * resource_desc.DepthOrArraySize = depth_or_array_size; resource_desc.MipLevels = miplevel_count; resource_desc.Format = format; - resource_desc.SampleDesc.Count = 1; + resource_desc.SampleDesc.Count = max(sample_count, 1); resource_desc.Flags = flags; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, initial_state, NULL, &IID_ID3D12Resource, (void **)&texture); @@ -618,7 +618,7 @@ static inline ID3D12Resource *create_default_texture2d_(unsigned int line, ID3D1 DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { return create_default_texture_(line, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, - width, height, array_size, miplevel_count, format, flags, initial_state); + width, height, array_size, miplevel_count, 1, format, flags, initial_state); }
#define create_default_texture3d(a, b, c, d, e, f, g, h) create_default_texture3d_(__LINE__, a, b, c, d, e, f, g, h) @@ -627,7 +627,7 @@ static inline ID3D12Resource *create_default_texture3d_(unsigned int line, ID3D1 DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state) { return create_default_texture_(line, device, D3D12_RESOURCE_DIMENSION_TEXTURE3D, - width, height, depth, miplevel_count, format, flags, initial_state); + width, height, depth, miplevel_count, 1, format, flags, initial_state); }
static void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src, diff --git a/tests/hlsl/get-sample-pos.shader_test b/tests/hlsl/get-sample-pos.shader_test new file mode 100644 index 000000000..5c4743d47 --- /dev/null +++ b/tests/hlsl/get-sample-pos.shader_test @@ -0,0 +1,20 @@ +[require] +shader model >= 4.1 +rgba float 4xmsaa + + +[srv 0] +format r32g32b32a32 float +size (2dms, 4, 2, 2) + +[pixel shader todo] +Texture2DMS<float4, 2> t; + +float4 main() : sv_target +{ + return float4(t.GetSamplePosition(0), t.GetSamplePosition(1)); +} + +[test] +todo draw quad +probe all rgba (-0.125, -0.375, 0.375, -0.125) diff --git a/tests/hlsl/rt-get-sample-info.shader_test b/tests/hlsl/rt-get-sample-info.shader_test new file mode 100644 index 000000000..f0a0e67a5 --- /dev/null +++ b/tests/hlsl/rt-get-sample-info.shader_test @@ -0,0 +1,35 @@ +[require] +shader model >= 4.1 +rgba float 4xmsaa + + +[rtv 0] +format r32g32b32a32 float +size (2dms, 4, 640, 480) + +[pixel shader todo] +float4 main() : sv_target +{ + return float4(GetRenderTargetSampleCount(), 0, 0, 0); +} + +[test] +todo draw quad +probe all rgba (4.0, 0.0, 0.0, 0.0) + + +[pixel shader todo] +uniform uint u; + +float4 main() : sv_target +{ + return float4(GetRenderTargetSamplePosition(u), GetRenderTargetSamplePosition(u + 1)); +} + +[test] +uniform 0 uint 0 +todo draw quad +probe all rgba (-0.125, -0.375, 0.375, -0.125) +uniform 0 uint 2 +todo draw quad +probe all rgba (-0.375, 0.125, 0.125, 0.375) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 5eafbcbe4..b9ac8f83f 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -332,6 +332,10 @@ static void parse_require_directive(struct shader_runner *runner, const char *li { runner->require_rov = true; } + else if (match_string(line, "rgba float 4xmsaa", &line)) + { + runner->require_rgba_float_4xmsaa = true; + } else { fatal_error("Unknown require directive '%s'.\n", line); @@ -508,6 +512,10 @@ static void parse_resource_directive(struct resource_params *resource, const cha { resource->dimension = RESOURCE_DIMENSION_2D; } + else if (sscanf(line, "( 2dms , %u , %u , %u ) ", &resource->sample_count, &resource->width, &resource->height) == 3) + { + resource->dimension = RESOURCE_DIMENSION_2D; + } else { fatal_error("Malformed resource size '%s'.\n", line); @@ -599,6 +607,7 @@ void init_resource(struct resource *resource, const struct resource_params *para resource->texel_size = params->texel_size; resource->width = params->width; resource->height = params->height; + resource->sample_count = params->sample_count; }
struct resource *shader_runner_get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot) @@ -1496,9 +1505,10 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c dxc_compiler ? "dxcompiler" : HLSL_COMPILER, caps->runner); if (caps->tag_count) trace_tags(caps); - trace(" float64: %u.\n", caps->float64); - trace(" int64: %u.\n", caps->int64); - trace(" rov: %u.\n", caps->rov); + trace(" float64: %u.\n", caps->float64); + trace(" int64: %u.\n", caps->int64); + trace(" rov: %u.\n", caps->rov); + trace("rgba float 4xmsaa: %u.\n", caps->rgba_float_4xmsaa);
if (!test_options.filename) fatal_error("No filename specified.\n"); diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 2f7e8fb25..a4eea7916 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -94,6 +94,7 @@ struct resource_params unsigned int stride; unsigned int width, height; unsigned int level_count; + unsigned int sample_count; uint8_t *data; size_t data_size, data_capacity; }; @@ -108,6 +109,7 @@ struct resource unsigned int size; unsigned int texel_size; unsigned int width, height; + unsigned int sample_count; };
struct input_element @@ -132,6 +134,7 @@ struct shader_runner_caps bool float64; bool int64; bool rov; + bool rgba_float_4xmsaa; };
static inline unsigned int shader_runner_caps_get_feature_flags(const struct shader_runner_caps *caps) @@ -162,6 +165,7 @@ struct shader_runner bool require_float64; bool require_int64; bool require_rov; + bool require_rgba_float_4xmsaa;
bool last_render_failed;
diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 1285ca41f..e181466f6 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -258,6 +258,7 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner) D3D11_FEATURE_DATA_DOUBLES doubles = {0}; unsigned int rt_width, rt_height; D3D11_RASTERIZER_DESC rs_desc; + UINT quality_levels; D3D11_VIEWPORT vp; HRESULT hr; RECT rect; @@ -284,6 +285,9 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner) ok(hr == S_OK, "Got hr %#lx.\n", hr); runner->caps.rov = options2.ROVsSupported;
+ runner->caps.rgba_float_4xmsaa = SUCCEEDED(ID3D11Device_CheckMultisampleQualityLevels(runner->device, + DXGI_FORMAT_R32G32B32A32_FLOAT, 4, &quality_levels)) && quality_levels; + rt_width = RENDER_TARGET_WIDTH; rt_height = RENDER_TARGET_HEIGHT; SetRect(&rect, 0, 0, rt_width, rt_height); @@ -371,7 +375,7 @@ static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re desc.MipLevels = params->level_count; desc.ArraySize = 1; desc.Format = params->format; - desc.SampleDesc.Count = 1; + desc.SampleDesc.Count = max(params->sample_count, 1); desc.Usage = D3D11_USAGE_DEFAULT; if (params->type == RESOURCE_TYPE_UAV) desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; @@ -384,6 +388,9 @@ static void init_resource_2d(struct d3d11_shader_runner *runner, struct d3d11_re { unsigned int buffer_offset = 0;
+ if (params->sample_count > 1) + fatal_error("Cannot upload data to an MSAA texture.\n"); + for (unsigned int level = 0; level < params->level_count; ++level) { unsigned int level_width = get_level_dimension(params->width, level); @@ -719,12 +726,15 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade { struct d3d11_shader_runner *runner = d3d11_shader_runner(r); struct d3d11_resource_readback *rb = malloc(sizeof(*rb)); + ID3D11Resource *resolved_resource = NULL, *src_resource; struct d3d11_resource *resource = d3d11_resource(res); D3D11_TEXTURE2D_DESC texture_desc; D3D11_MAPPED_SUBRESOURCE map_desc; D3D11_BUFFER_DESC buffer_desc; + bool is_ms = false; HRESULT hr;
+ src_resource = resource->resource; switch (resource->r.type) { case RESOURCE_TYPE_RENDER_TARGET: @@ -742,12 +752,25 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade else { ID3D11Texture2D_GetDesc(resource->texture, &texture_desc); + is_ms = texture_desc.SampleDesc.Count > 1; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; 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 (is_ms) + { + texture_desc.Usage = D3D11_USAGE_DEFAULT; + hr = ID3D11Device_CreateTexture2D(runner->device, &texture_desc, NULL, + (ID3D11Texture2D **)&resolved_resource); + ok(hr == S_OK, "Failed to create MS texture, hr %#lx.\n", hr); + ID3D11DeviceContext_ResolveSubresource(runner->immediate_context, resolved_resource, 0, + resource->resource, 0, texture_desc.Format); + src_resource = resolved_resource; + } } break;
@@ -759,10 +782,13 @@ static struct resource_readback *d3d11_runner_get_resource_readback(struct shade if (resource->is_uav_counter) ID3D11DeviceContext_CopyStructureCount(runner->immediate_context, (ID3D11Buffer *)rb->resource, 0, resource->uav); else - ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, resource->resource); + ID3D11DeviceContext_CopyResource(runner->immediate_context, rb->resource, src_resource); hr = ID3D11DeviceContext_Map(runner->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &map_desc); ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr);
+ if (resolved_resource) + ID3D11Resource_Release(resolved_resource); + rb->rb.data = map_desc.pData; rb->rb.row_pitch = map_desc.RowPitch; rb->rb.width = resource->r.width; diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 9bf7bb248..c0444728d 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -136,8 +136,19 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co if (params->slot >= D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT) fatal_error("RTV slot %u is too high.\n", params->slot);
- resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, - params->format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); + if (params->sample_count) + { + if (params->level_count > 1) + fatal_error("Multisample resource has multiple levels.\n"); + resource->resource = create_default_texture_(__LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, + params->width, params->height, 1, 1, params->sample_count, params->format, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + else + { + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, + 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; @@ -169,13 +180,25 @@ static struct resource *d3d12_runner_create_resource(struct shader_runner *r, co } else { - resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, - params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); - 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_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - reset_command_list(test_context->list, test_context->allocator); + if (params->sample_count) + { + if (params->level_count > 1) + fatal_error("Multisample resource has multiple levels.\n"); + /* Multisampled textures must have ALLOW_RENDER_TARGET set. */ + resource->resource = create_default_texture_(__LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, + params->width, params->height, 1, 1, params->sample_count, params->format, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_DEST); + } + else + { + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, + params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); + 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_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + reset_command_list(test_context->list, test_context->allocator); + } ID3D12Device_CreateShaderResourceView(device, resource->resource, NULL, get_cpu_descriptor_handle(test_context, runner->heap, resource->r.slot)); } @@ -439,8 +462,8 @@ static bool d3d12_runner_draw(struct shader_runner *r, ID3D12CommandQueue *queue = test_context->queue; D3D12_INPUT_ELEMENT_DESC *input_element_descs; ID3D12Device *device = test_context->device; + unsigned int uniform_index, sample_count; ID3D10Blob *vs_code, *ps_code; - unsigned int uniform_index; unsigned int rtv_count = 0; ID3D12PipelineState *pso; HRESULT hr; @@ -465,7 +488,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, test_context->root_signature = d3d12_runner_create_root_signature(runner, queue, test_context->allocator, command_list, &uniform_index);
- for (i = 0; i < runner->r.resource_count; ++i) + for (i = 0, sample_count = 1; i < runner->r.resource_count; ++i) { struct d3d12_resource *resource = d3d12_resource(runner->r.resources[i]);
@@ -474,6 +497,8 @@ static bool d3d12_runner_draw(struct shader_runner *r, 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; + if (resource->r.sample_count) + sample_count = resource->r.sample_count; } }
@@ -484,7 +509,7 @@ static bool d3d12_runner_draw(struct shader_runner *r, pso_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - pso_desc.SampleDesc.Count = 1; + pso_desc.SampleDesc.Count = sample_count; pso_desc.SampleMask = ~(UINT)0; pso_desc.pRootSignature = test_context->root_signature;
@@ -635,6 +660,7 @@ static void d3d12_runner_init_caps(struct d3d12_shader_runner *runner) runner->caps.float64 = options.DoublePrecisionFloatShaderOps; runner->caps.int64 = options1.Int64ShaderOps; runner->caps.rov = options.ROVsSupported; + runner->caps.rgba_float_4xmsaa = true; }
void run_shader_tests_d3d12(void *dxc_compiler) diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index e56eccab0..6e1b6950c 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -157,6 +157,8 @@ static bool check_egl_client_extension(const char *extension)
static bool gl_runner_init(struct gl_runner *runner, enum shading_language language) { + PFNGLGETINTERNALFORMATIVPROC glGetInternalformativ; + GLint tex_max_sample_count, rt_max_sample_count; PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; const char *glsl_version = NULL; EGLDeviceEXT *devices; @@ -263,6 +265,13 @@ static bool gl_runner_init(struct gl_runner *runner, enum shading_language langu runner->caps.minimum_shader_model = SHADER_MODEL_4_0; runner->caps.maximum_shader_model = SHADER_MODEL_5_1;
+ if ((glGetInternalformativ = (void *)eglGetProcAddress("glGetInternalformativ"))) + { + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA32F, GL_SAMPLES, 1, &tex_max_sample_count); + glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA32F, GL_SAMPLES, 1, &rt_max_sample_count); + runner->caps.rgba_float_4xmsaa = tex_max_sample_count >= 4 && rt_max_sample_count >= 4; + } + trace("Using device %u.\n", i); runner->display = display; runner->context = context; diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index a3bbf170c..8aaf98215 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -1544,6 +1544,8 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) runner->caps.rov = false; }
+ runner->caps.rgba_float_4xmsaa = true; + vr = VK_CALL(vkCreateDevice(runner->phys_device, &device_desc, NULL, &device)); free(enabled_extensions.names); if (vr)
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 21 +++++++++++++++++++++ tests/hlsl/rt-get-sample-info.shader_test | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 8fa632d73..7946c4dbe 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -403,6 +403,7 @@ enum dx_intrinsic_opcode DX_TEXTURE_GATHER_CMP = 74, DX_TEX2DMS_GET_SAMPLE_POS = 75, DX_RT_GET_SAMPLE_POS = 76, + DX_RT_GET_SAMPLE_COUNT = 77, DX_ATOMIC_BINOP = 78, DX_ATOMIC_CMP_XCHG = 79, DX_BARRIER = 80, @@ -5015,6 +5016,25 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr dst_param->reg = resource->u.handle.reg; }
+static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SAMPLE_INFO); + ins->flags = VKD3DSI_SAMPLE_INFO_UINT; + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + vsir_register_init(&src_param->reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + ins->dst->reg.data_type = VKD3D_DATA_FLOAT; +} + static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -5495,6 +5515,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_Z ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_RSQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_RT_GET_SAMPLE_COUNT ] = {"i", "", sm6_parser_emit_dx_get_sample_count}, [DX_RT_GET_SAMPLE_POS ] = {"o", "i", sm6_parser_emit_dx_get_sample_pos}, [DX_SAMPLE ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, [DX_SAMPLE_B ] = {"o", "HHffffiiiff", sm6_parser_emit_dx_sample}, diff --git a/tests/hlsl/rt-get-sample-info.shader_test b/tests/hlsl/rt-get-sample-info.shader_test index d26b4db8f..d7939db35 100644 --- a/tests/hlsl/rt-get-sample-info.shader_test +++ b/tests/hlsl/rt-get-sample-info.shader_test @@ -14,7 +14,7 @@ float4 main() : sv_target }
[test] -todo draw quad +todo(sm<6 | glsl) draw quad probe all rgba (4.0, 0.0, 0.0, 0.0)
@@ -132,6 +134,7 @@ struct shader_runner_caps bool float64; bool int64; bool rov; + bool rgba_float_4xmsaa; }; static inline unsigned int shader_runner_caps_get_feature_flags(const struct shader_runner_caps *caps)
I suppose that's fine for a single format and sample count combination, but I'm not sure that can scale. Could we just allow runner->ops->create_resource() to optionally fail, and then skip any tests referencing such a failed resource?
+ if (params->sample_count) + { + if (params->level_count > 1) + fatal_error("Multisample resource has multiple levels.\n"); + resource->resource = create_default_texture_(__LINE__, device, D3D12_RESOURCE_DIMENSION_TEXTURE2D, + params->width, params->height, 1, 1, params->sample_count, params->format, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + else + { + resource->resource = create_default_texture2d(device, params->width, params->height, 1, params->level_count, + params->format, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET); + }
Right, but create_default_texture2d() can be trivially replaced with create_default_texture_() as well, and then the two branches can be merged.
+ if ((glGetInternalformativ = (void *)eglGetProcAddress("glGetInternalformativ"))) + { + glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA32F, GL_SAMPLES, 1, &tex_max_sample_count); + glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA32F, GL_SAMPLES, 1, &rt_max_sample_count); + runner->caps.rgba_float_4xmsaa = tex_max_sample_count >= 4 && rt_max_sample_count >= 4; + }
You don't need to use eglGetProcAddress() for glGetInternalformativ(), libOpenGL.so exports all the OpenGL 4.5 core and compat entry points, and glGetInternalformativ() is GL 4.2. You probably do need to check that GL_ARB_internalformat_query is supported. We don't use renderbuffers.
I suppose that's fine for a single format and sample count combination, but I'm not sure that can scale.
Do we need the shader_test syntax to scale? In the abstract, I've always seen it as a way to complement the C tests where it's easier, but not that it'll always be the best way to write tests. This especially because one thing I've wanted to add, but haven't gotten around to finishing and submitting, is a way to invoke the shader runner from C, which would mostly be a way to take advantage of the "write once, run on multiple runners" ability while using more complex things like control flow. (I've probably mentioned this before).
More concretely,
* if we just need a way to test "multisampling", then we don't need more than one format, and just looking over the d3d11 tests I don't think I see any that really care what that format is, nor can I easily anticipate one;
* if we do need it to scale better, it may be better to achieve that in C [and just earmark this test for conversion].