Skip to content

Commit 079b95c

Browse files
vkd3d: proper return values for formats that are valid but not supported.
Signed-off-by: David McCloskey <dave@juicelabs.co>
1 parent e641163 commit 079b95c

File tree

4 files changed

+188
-8
lines changed

4 files changed

+188
-8
lines changed

libs/vkd3d/device.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,6 +3731,12 @@ static HRESULT d3d12_device_get_format_support(struct d3d12_device *device, D3D1
37313731
data->Support1 = D3D12_FORMAT_SUPPORT1_NONE;
37323732
data->Support2 = D3D12_FORMAT_SUPPORT2_NONE;
37333733

3734+
if (!is_valid_format(data->Format))
3735+
{
3736+
WARN("Invalid format %d.\n", data->Format);
3737+
return E_INVALIDARG;
3738+
}
3739+
37343740
if (!data->Format)
37353741
{
37363742
data->Support1 = D3D12_FORMAT_SUPPORT1_BUFFER;
@@ -3743,10 +3749,7 @@ static HRESULT d3d12_device_get_format_support(struct d3d12_device *device, D3D1
37433749
if (!(format = vkd3d_get_format(device, data->Format, false)))
37443750
format = vkd3d_get_format(device, data->Format, true);
37453751
if (!format)
3746-
{
3747-
FIXME("Unhandled format %#x.\n", data->Format);
3748-
return E_INVALIDARG;
3749-
}
3752+
return E_FAIL;
37503753

37513754
/* Special opaque formats. */
37523755
if (data->Format == DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE ||

libs/vkd3d/utils.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,11 @@ const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
674674
{
675675
const struct vkd3d_format *format;
676676

677-
if (dxgi_format > VKD3D_MAX_DXGI_FORMAT)
677+
if (!is_valid_format(dxgi_format))
678+
{
679+
ERR("Invalid format %d.\n", dxgi_format);
678680
return NULL;
681+
}
679682

680683
/* If we request a depth-stencil format (or typeless variant) that is planar,
681684
* there cannot be any ambiguity which format to select, we must choose a depth-stencil format.
@@ -913,6 +916,17 @@ bool is_valid_resource_state(D3D12_RESOURCE_STATES state)
913916
return true;
914917
}
915918

919+
bool is_valid_format(DXGI_FORMAT dxgi_format)
920+
{
921+
if (dxgi_format >= DXGI_FORMAT_UNKNOWN && dxgi_format <= DXGI_FORMAT_B4G4R4A4_UNORM)
922+
return true;
923+
if (dxgi_format >= DXGI_FORMAT_P208 && dxgi_format <= DXGI_FORMAT_V408)
924+
return true;
925+
if (dxgi_format >= DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE && dxgi_format <= DXGI_FORMAT_A4B4G4R4_UNORM)
926+
return true;
927+
return false;
928+
}
929+
916930
HRESULT return_interface(void *iface, REFIID iface_iid,
917931
REFIID requested_iid, void **object)
918932
{

libs/vkd3d/vkd3d_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5338,6 +5338,8 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level);
53385338
bool is_valid_resource_state(D3D12_RESOURCE_STATES state);
53395339
bool is_write_resource_state(D3D12_RESOURCE_STATES state);
53405340

5341+
bool is_valid_format(DXGI_FORMAT format);
5342+
53415343
HRESULT return_interface(void *iface, REFIID iface_iid,
53425344
REFIID requested_iid, void **object);
53435345

tests/d3d12_device.c

Lines changed: 164 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ void test_check_feature_support(void)
107107

108108
static const D3D_FEATURE_LEVEL all_feature_levels[] =
109109
{
110+
D3D_FEATURE_LEVEL_12_2,
110111
D3D_FEATURE_LEVEL_12_1,
111112
D3D_FEATURE_LEVEL_12_0,
112113
D3D_FEATURE_LEVEL_11_1,
@@ -119,6 +120,7 @@ void test_check_feature_support(void)
119120
};
120121
static const D3D_FEATURE_LEVEL d3d12_feature_levels[] =
121122
{
123+
D3D_FEATURE_LEVEL_12_2,
122124
D3D_FEATURE_LEVEL_12_1,
123125
D3D_FEATURE_LEVEL_12_0,
124126
D3D_FEATURE_LEVEL_11_1,
@@ -336,11 +338,96 @@ static const DXGI_FORMAT depth_stencil_formats[] =
336338
void test_format_support(void)
337339
{
338340
D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support;
341+
D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
342+
bool required_but_fails;
343+
bool unspecified_format;
344+
bool optional_format;
339345
ID3D12Device *device;
346+
DXGI_FORMAT format;
340347
ULONG refcount;
341348
unsigned int i;
342349
HRESULT hr;
343350

351+
static const DXGI_FORMAT known_required_but_fails[] =
352+
{
353+
DXGI_FORMAT_R8G8_B8G8_UNORM,
354+
DXGI_FORMAT_G8R8_G8B8_UNORM,
355+
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
356+
DXGI_FORMAT_NV12,
357+
DXGI_FORMAT_420_OPAQUE,
358+
DXGI_FORMAT_YUY2,
359+
};
360+
361+
#define MAX_FORMAT_VALUE DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE
362+
363+
const struct dxgi_format_list
364+
{
365+
D3D_FEATURE_LEVEL feature_level;
366+
DXGI_FORMAT optional_formats[MAX_FORMAT_VALUE];
367+
DXGI_FORMAT unspecified_formats[MAX_FORMAT_VALUE];
368+
} *dxgi_format, dxgi_format_list[] = {
369+
/*
370+
https://devblogs.microsoft.com/directx/new-in-directx-feature-level-12_2/
371+
https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html
372+
*/
373+
{D3D_FEATURE_LEVEL_12_2,
374+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11,
375+
DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
376+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408}},
377+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/hardware-support-for-direct3d-12-1-formats.md */
378+
{D3D_FEATURE_LEVEL_12_1,
379+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11,
380+
DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
381+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
382+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
383+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/hardware-support-for-direct3d-12-0-formats.md */
384+
{D3D_FEATURE_LEVEL_12_0,
385+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11,
386+
DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
387+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
388+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
389+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/format-support-for-direct3d-11-1-feature-level-hardware.md */
390+
{D3D_FEATURE_LEVEL_11_1,
391+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11,
392+
DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
393+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
394+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
395+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware.md */
396+
{D3D_FEATURE_LEVEL_11_0,
397+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11,
398+
DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
399+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
400+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
401+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/format-support-for-direct3d-feature-level-10-1-hardware.md */
402+
{D3D_FEATURE_LEVEL_10_1,
403+
{DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016, DXGI_FORMAT_Y210,
404+
DXGI_FORMAT_Y216, DXGI_FORMAT_NV11, DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
405+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
406+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
407+
/* https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/direct3ddxgi/format-support-for-direct3d-feature-level-10-1-hardware.md */
408+
{D3D_FEATURE_LEVEL_10_0,
409+
{DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, DXGI_FORMAT_AYUV, DXGI_FORMAT_Y410, DXGI_FORMAT_Y416, DXGI_FORMAT_P010, DXGI_FORMAT_P016,
410+
DXGI_FORMAT_Y210, DXGI_FORMAT_Y216, DXGI_FORMAT_NV11, DXGI_FORMAT_AI44, DXGI_FORMAT_IA44, DXGI_FORMAT_P8, DXGI_FORMAT_A8P8},
411+
{DXGI_FORMAT_R1_UNORM, DXGI_FORMAT_P208, DXGI_FORMAT_V208, DXGI_FORMAT_V408,
412+
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE}},
413+
};
414+
415+
#undef MAX_FORMAT_VALUE
416+
417+
static const D3D_FEATURE_LEVEL all_feature_levels[] =
418+
{
419+
D3D_FEATURE_LEVEL_12_2,
420+
D3D_FEATURE_LEVEL_12_1,
421+
D3D_FEATURE_LEVEL_12_0,
422+
D3D_FEATURE_LEVEL_11_1,
423+
D3D_FEATURE_LEVEL_11_0,
424+
D3D_FEATURE_LEVEL_10_1,
425+
D3D_FEATURE_LEVEL_10_0,
426+
D3D_FEATURE_LEVEL_9_3,
427+
D3D_FEATURE_LEVEL_9_2,
428+
D3D_FEATURE_LEVEL_9_1,
429+
};
430+
344431
if (!(device = create_device()))
345432
{
346433
skip("Failed to create device.\n");
@@ -356,14 +443,88 @@ void test_format_support(void)
356443
ok(!format_support.Support2 || format_support.Support2 == D3D12_FORMAT_SUPPORT2_TILED,
357444
"Got unexpected support2 %#x.\n", format_support.Support2);
358445

359-
for (i = 0; i < ARRAY_SIZE(depth_stencil_formats); ++i)
446+
memset(&feature_levels, 0, sizeof(feature_levels));
447+
feature_levels.NumFeatureLevels = ARRAY_SIZE(all_feature_levels);
448+
feature_levels.pFeatureLevelsRequested = all_feature_levels;
449+
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
450+
&feature_levels, sizeof(feature_levels));
451+
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
452+
453+
for (i = 0; i < ARRAY_SIZE(dxgi_format_list); ++i)
360454
{
455+
if (dxgi_format_list[i].feature_level == feature_levels.MaxSupportedFeatureLevel)
456+
{
457+
dxgi_format = &dxgi_format_list[i];
458+
break;
459+
}
460+
}
461+
462+
for (format = 0; format <= DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE; ++format)
463+
{
464+
/* Undefined range, skip */
465+
if ((format > DXGI_FORMAT_B4G4R4A4_UNORM && format < DXGI_FORMAT_P208) ||
466+
(format > DXGI_FORMAT_V408 && format < DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE))
467+
continue;
468+
469+
vkd3d_test_set_context("format %#x", format);
470+
471+
required_but_fails = false;
472+
unspecified_format = false;
473+
optional_format = false;
474+
475+
for (i = 0; i < ARRAY_SIZE(known_required_but_fails); ++i)
476+
{
477+
if (known_required_but_fails[i] == format)
478+
{
479+
required_but_fails = true;
480+
break;
481+
}
482+
}
483+
484+
if (!required_but_fails)
485+
{
486+
/* Check if the format is unspecified or optional */
487+
for (i = 0; i < ARRAY_SIZE(dxgi_format->unspecified_formats); ++i)
488+
{
489+
/* Fixed size list with only part of the list filled */
490+
if (dxgi_format->unspecified_formats[i] == DXGI_FORMAT_UNKNOWN)
491+
break;
492+
if (dxgi_format->unspecified_formats[i] == format)
493+
{
494+
unspecified_format = true;
495+
break;
496+
}
497+
}
498+
499+
if (!unspecified_format)
500+
{
501+
for (i = 0; i < ARRAY_SIZE(dxgi_format->optional_formats); ++i)
502+
{
503+
/* Fixed size list with only part of the list filled */
504+
if (dxgi_format->optional_formats[i] == DXGI_FORMAT_UNKNOWN)
505+
break;
506+
if (dxgi_format->optional_formats[i] == format)
507+
{
508+
optional_format = true;
509+
break;
510+
}
511+
}
512+
}
513+
}
514+
361515
memset(&format_support, 0, sizeof(format_support));
362-
format_support.Format = depth_stencil_formats[i];
516+
format_support.Format = format;
363517
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_SUPPORT,
364518
&format_support, sizeof(format_support));
365-
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
519+
520+
if (unspecified_format)
521+
ok(hr == S_OK || hr == E_FAIL, "Unspecified format %d got unexpected hr %#x.\n", format, hr);
522+
else if (optional_format)
523+
ok(hr == S_OK || hr == E_FAIL, "Optional format %d got unexpected hr %#x.\n", format, hr);
524+
else
525+
todo_if(required_but_fails) ok(hr == S_OK, "Format %d got unexpected hr %#x.\n", format, hr);
366526
}
527+
vkd3d_test_set_context(NULL);
367528

368529
refcount = ID3D12Device_Release(device);
369530
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);

0 commit comments

Comments
 (0)