libs/vkd3d: Validate initial resource state.

This commit is contained in:
Józef Kucia 2016-10-19 13:10:12 +02:00
parent f601cbc04a
commit 69cd100d48
5 changed files with 73 additions and 7 deletions

View File

@ -250,7 +250,7 @@ typedef enum D3D12_RESOURCE_STATES
D3D12_RESOURCE_STATE_DEPTH_READ = 0x20, D3D12_RESOURCE_STATE_DEPTH_READ = 0x20,
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE = 0x40, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE = 0x40,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE = 0x80, 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_INDIRECT_ARGUMENT = 0x200,
D3D12_RESOURCE_STATE_COPY_DEST = 0x400, D3D12_RESOURCE_STATE_COPY_DEST = 0x400,
D3D12_RESOURCE_STATE_COPY_SOURCE = 0x800, D3D12_RESOURCE_STATE_COPY_SOURCE = 0x800,

View File

@ -639,6 +639,12 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
return E_INVALIDARG; 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) if (optimized_clear_value && desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{ {
WARN("Optimized clear value must be NULL for buffers.\n"); WARN("Optimized clear value must be NULL for buffers.\n");

View File

@ -75,7 +75,7 @@ bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count
return true; 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[] = 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) for (i = 0; i < ARRAY_SIZE(valid_feature_levels); ++i)
{ {
if (valid_feature_levels[i] == feature_level) 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; 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, HRESULT return_interface(IUnknown *iface, REFIID iface_riid,
REFIID requested_riid, void **object) REFIID requested_riid, void **object)
{ {

View File

@ -357,8 +357,10 @@ struct vkd3d_format
const struct vkd3d_format *vkd3d_get_format(DXGI_FORMAT dxgi_format) DECLSPEC_HIDDEN; 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 is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) DECLSPEC_HIDDEN;
BOOL check_feature_level_support(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, HRESULT return_interface(IUnknown *iface, REFIID iface_riid,
REFIID requested_riid, void **object) DECLSPEC_HIDDEN; REFIID requested_riid, void **object) DECLSPEC_HIDDEN;

View File

@ -890,6 +890,11 @@ static void test_create_committed_resource(void)
refcount = ID3D12Resource_Release(resource); refcount = ID3D12Resource_Release(resource);
ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount); 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. */ /* For D3D12_RESOURCE_STATE_RENDER_TARGET the D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET flag is required. */
resource_desc.Flags = 0; resource_desc.Flags = 0;
hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,