From 69cd100d48dcae651e7892bcdc7c57adbe0e3e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Wed, 19 Oct 2016 13:10:12 +0200 Subject: [PATCH] libs/vkd3d: Validate initial resource state. --- include/d3d12.idl | 2 +- libs/vkd3d/resource.c | 6 ++++ libs/vkd3d/utils.c | 61 +++++++++++++++++++++++++++++++++++--- libs/vkd3d/vkd3d_private.h | 6 ++-- tests/d3d12.c | 5 ++++ 5 files changed, 73 insertions(+), 7 deletions(-) diff --git a/include/d3d12.idl b/include/d3d12.idl index 0c39f160..a386378c 100644 --- a/include/d3d12.idl +++ b/include/d3d12.idl @@ -250,7 +250,7 @@ typedef enum D3D12_RESOURCE_STATES D3D12_RESOURCE_STATE_DEPTH_READ = 0x20, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE = 0x40, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE = 0x80, - D3D12_RESOURCE_STATE_STREAM_OUTPUT = 0x100, + D3D12_RESOURCE_STATE_STREAM_OUT = 0x100, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT = 0x200, D3D12_RESOURCE_STATE_COPY_DEST = 0x400, D3D12_RESOURCE_STATE_COPY_SOURCE = 0x800, diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index d7b8f542..cba10b80 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -639,6 +639,12 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st return E_INVALIDARG; } + if (!is_valid_resource_state(initial_state)) + { + WARN("Invalid initial resource state %#x.\n", initial_state); + return E_INVALIDARG; + } + if (optimized_clear_value && desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { WARN("Optimized clear value must be NULL for buffers.\n"); diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index 6235ad13..1dccfc09 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -75,7 +75,7 @@ bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count return true; } -BOOL is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) +bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) { static const D3D_FEATURE_LEVEL valid_feature_levels[] = { @@ -94,17 +94,70 @@ BOOL is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) for (i = 0; i < ARRAY_SIZE(valid_feature_levels); ++i) { if (valid_feature_levels[i] == feature_level) - return TRUE; + return true; } - return FALSE; + return false; } -BOOL check_feature_level_support(D3D_FEATURE_LEVEL feature_level) +bool check_feature_level_support(D3D_FEATURE_LEVEL feature_level) { return feature_level <= D3D_FEATURE_LEVEL_11_0; } +static bool is_write_resource_state(D3D12_RESOURCE_STATES state) +{ + return state & (D3D12_RESOURCE_STATE_RENDER_TARGET + | D3D12_RESOURCE_STATE_UNORDERED_ACCESS + | D3D12_RESOURCE_STATE_DEPTH_WRITE + | D3D12_RESOURCE_STATE_STREAM_OUT + | D3D12_RESOURCE_STATE_COPY_DEST + | D3D12_RESOURCE_STATE_RESOLVE_DEST); +} + +static bool is_power_of_two(unsigned int x) +{ + return x && !(x & (x -1)); +} + +bool is_valid_resource_state(D3D12_RESOURCE_STATES state) +{ + const D3D12_RESOURCE_STATES valid_states = + D3D12_RESOURCE_STATE_COMMON | + D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER | + D3D12_RESOURCE_STATE_INDEX_BUFFER | + D3D12_RESOURCE_STATE_RENDER_TARGET | + D3D12_RESOURCE_STATE_UNORDERED_ACCESS | + D3D12_RESOURCE_STATE_DEPTH_WRITE | + D3D12_RESOURCE_STATE_DEPTH_READ | + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | + D3D12_RESOURCE_STATE_STREAM_OUT | + D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT | + D3D12_RESOURCE_STATE_COPY_DEST | + D3D12_RESOURCE_STATE_COPY_SOURCE | + D3D12_RESOURCE_STATE_RESOLVE_DEST | + D3D12_RESOURCE_STATE_RESOLVE_SOURCE | + D3D12_RESOURCE_STATE_GENERIC_READ | + D3D12_RESOURCE_STATE_PRESENT | + D3D12_RESOURCE_STATE_PREDICATION; + + if (state & ~valid_states) + { + WARN("Invalid resource states %#x.\n", state & ~valid_states); + return false; + } + + /* Exactly one bit must be set for write states. */ + if (is_write_resource_state(state) && !is_power_of_two(state)) + { + WARN("Write state cannot be mixed with other states: %#x.\n", state); + return false; + } + + return true; +} + HRESULT return_interface(IUnknown *iface, REFIID iface_riid, REFIID requested_riid, void **object) { diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 8498543b..2849b031 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -357,8 +357,10 @@ struct vkd3d_format const struct vkd3d_format *vkd3d_get_format(DXGI_FORMAT dxgi_format) DECLSPEC_HIDDEN; -BOOL is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN; -BOOL check_feature_level_support(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN; +bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN; +bool check_feature_level_support(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN; + +bool is_valid_resource_state(D3D12_RESOURCE_STATES state) DECLSPEC_HIDDEN; HRESULT return_interface(IUnknown *iface, REFIID iface_riid, REFIID requested_riid, void **object) DECLSPEC_HIDDEN; diff --git a/tests/d3d12.c b/tests/d3d12.c index 818b56f2..04b40eda 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -890,6 +890,11 @@ static void test_create_committed_resource(void) refcount = ID3D12Resource_Release(resource); ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount); + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + &clear_value, &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + /* For D3D12_RESOURCE_STATE_RENDER_TARGET the D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET flag is required. */ resource_desc.Flags = 0; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,