vkd3d: Add more stringent validation for CreateCommandSignature.
The runtime is specified to validate certain things. Also, be more robust against unsupported command signatures, since we might need to draw/dispatch at an offset. Avoids hard GPU crashes. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
parent
9029d1ae23
commit
300d6e7166
|
@ -9203,6 +9203,10 @@ static void STDMETHODCALLTYPE d3d12_command_list_ExecuteIndirect(d3d12_command_l
|
|||
return;
|
||||
}
|
||||
|
||||
/* Temporary workaround, since we cannot parse non-draw arguments yet. Point directly
|
||||
* to the first argument. Should avoid hard crashes for now. */
|
||||
arg_buffer_offset += sig_impl->argument_buffer_offset;
|
||||
|
||||
for (i = 0; i < signature_desc->NumArgumentDescs; ++i)
|
||||
{
|
||||
const D3D12_INDIRECT_ARGUMENT_DESC *arg_desc = &signature_desc->pArgumentDescs[i];
|
||||
|
@ -11889,36 +11893,137 @@ CONST_VTBL struct ID3D12CommandSignatureVtbl d3d12_command_signature_vtbl =
|
|||
d3d12_command_signature_GetDevice,
|
||||
};
|
||||
|
||||
HRESULT d3d12_command_signature_create(struct d3d12_device *device, const D3D12_COMMAND_SIGNATURE_DESC *desc,
|
||||
HRESULT d3d12_command_signature_create(struct d3d12_device *device, struct d3d12_root_signature *root_signature,
|
||||
const D3D12_COMMAND_SIGNATURE_DESC *desc,
|
||||
struct d3d12_command_signature **signature)
|
||||
{
|
||||
struct d3d12_command_signature *object;
|
||||
bool requires_root_signature = false;
|
||||
uint32_t argument_buffer_offset = 0;
|
||||
uint32_t signature_size = 0;
|
||||
bool has_action = false;
|
||||
unsigned int i;
|
||||
bool is_action;
|
||||
HRESULT hr;
|
||||
|
||||
for (i = 0; i < desc->NumArgumentDescs; ++i)
|
||||
{
|
||||
const D3D12_INDIRECT_ARGUMENT_DESC *argument_desc = &desc->pArgumentDescs[i];
|
||||
is_action = false;
|
||||
|
||||
switch (argument_desc->Type)
|
||||
{
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
|
||||
if (i != desc->NumArgumentDescs - 1)
|
||||
{
|
||||
WARN("Draw/dispatch must be the last element of a command signature.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
argument_buffer_offset = signature_size;
|
||||
signature_size += sizeof(D3D12_DRAW_ARGUMENTS);
|
||||
is_action = true;
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED:
|
||||
argument_buffer_offset = signature_size;
|
||||
signature_size += sizeof(D3D12_DRAW_INDEXED_ARGUMENTS);
|
||||
is_action = true;
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH:
|
||||
argument_buffer_offset = signature_size;
|
||||
signature_size += sizeof(D3D12_DISPATCH_ARGUMENTS);
|
||||
is_action = true;
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_RAYS:
|
||||
argument_buffer_offset = signature_size;
|
||||
signature_size += sizeof(D3D12_DISPATCH_RAYS_DESC);
|
||||
is_action = true;
|
||||
FIXME("Unsupported indirect dispatch rays.\n");
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH_MESH:
|
||||
argument_buffer_offset = signature_size;
|
||||
signature_size += sizeof(D3D12_DISPATCH_MESH_ARGUMENTS);
|
||||
is_action = true;
|
||||
FIXME("Unsupported indirect dispatch mesh.\n");
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT:
|
||||
requires_root_signature = true;
|
||||
signature_size += argument_desc->Constant.Num32BitValuesToSet * sizeof(uint32_t);
|
||||
FIXME("Unsupported indirect argument type CONSTANT.\n");
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW:
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW:
|
||||
requires_root_signature = true;
|
||||
/* The command signature payload is *not* aligned. */
|
||||
signature_size += sizeof(D3D12_GPU_VIRTUAL_ADDRESS);
|
||||
FIXME("Unsupported indirect root descriptor type: %u.\n", argument_desc->Type);
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW:
|
||||
/* The command signature payload is *not* aligned. */
|
||||
signature_size += sizeof(D3D12_VERTEX_BUFFER_VIEW);
|
||||
FIXME("Unsupported indirect VBV.\n");
|
||||
break;
|
||||
|
||||
case D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW:
|
||||
/* The command signature payload is *not* aligned. */
|
||||
signature_size += sizeof(D3D12_INDEX_BUFFER_VIEW);
|
||||
FIXME("Unsupported indirect IBV.\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("Unsupported indirect argument type: %u.\n", argument_desc->Type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_action)
|
||||
{
|
||||
if (has_action)
|
||||
{
|
||||
ERR("Using multiple action commands per command signature is invalid.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (i != desc->NumArgumentDescs - 1)
|
||||
{
|
||||
WARN("Action command must be the last element of a command signature.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
has_action = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_action)
|
||||
{
|
||||
ERR("Command signature must have exactly one action command.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (desc->ByteStride < signature_size)
|
||||
{
|
||||
ERR("Command signature stride %u must be at least %u bytes.\n",
|
||||
desc->ByteStride, signature_size);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (requires_root_signature && !root_signature)
|
||||
{
|
||||
ERR("Command signature requires root signature, but is not provided.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else if (!requires_root_signature && root_signature)
|
||||
{
|
||||
ERR("Command signature requires root signature, root signature must be NULL.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!(object = vkd3d_malloc(sizeof(*object))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->ID3D12CommandSignature_iface.lpVtbl = &d3d12_command_signature_vtbl;
|
||||
object->argument_buffer_offset = argument_buffer_offset;
|
||||
object->refcount = 1;
|
||||
|
||||
object->desc = *desc;
|
||||
|
|
|
@ -4297,9 +4297,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetStablePowerState(d3d12_device_i
|
|||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(d3d12_device_iface *iface,
|
||||
const D3D12_COMMAND_SIGNATURE_DESC *desc, ID3D12RootSignature *root_signature,
|
||||
const D3D12_COMMAND_SIGNATURE_DESC *desc, ID3D12RootSignature *root_signature_iface,
|
||||
REFIID iid, void **command_signature)
|
||||
{
|
||||
struct d3d12_root_signature *root_signature = impl_from_ID3D12RootSignature(root_signature_iface);
|
||||
struct d3d12_device *device = impl_from_ID3D12Device(iface);
|
||||
struct d3d12_command_signature *object;
|
||||
HRESULT hr;
|
||||
|
@ -4307,7 +4308,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandSignature(d3d12_devic
|
|||
TRACE("iface %p, desc %p, root_signature %p, iid %s, command_signature %p.\n",
|
||||
iface, desc, root_signature, debugstr_guid(iid), command_signature);
|
||||
|
||||
if (FAILED(hr = d3d12_command_signature_create(device, desc, &object)))
|
||||
if (FAILED(hr = d3d12_command_signature_create(device, root_signature, desc, &object)))
|
||||
return hr;
|
||||
|
||||
return return_interface(&object->ID3D12CommandSignature_iface,
|
||||
|
|
|
@ -2225,13 +2225,15 @@ struct d3d12_command_signature
|
|||
LONG refcount;
|
||||
|
||||
D3D12_COMMAND_SIGNATURE_DESC desc;
|
||||
uint32_t argument_buffer_offset;
|
||||
|
||||
struct d3d12_device *device;
|
||||
|
||||
struct vkd3d_private_store private_store;
|
||||
};
|
||||
|
||||
HRESULT d3d12_command_signature_create(struct d3d12_device *device, const D3D12_COMMAND_SIGNATURE_DESC *desc,
|
||||
HRESULT d3d12_command_signature_create(struct d3d12_device *device, struct d3d12_root_signature *root_signature,
|
||||
const D3D12_COMMAND_SIGNATURE_DESC *desc,
|
||||
struct d3d12_command_signature **signature);
|
||||
|
||||
static inline struct d3d12_command_signature *impl_from_ID3D12CommandSignature(ID3D12CommandSignature *iface)
|
||||
|
|
Loading…
Reference in New Issue