Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- v2: Remove unnecessary struct d3d12_device *device. --- libs/vkd3d/device.c | 4 +-- libs/vkd3d/resource.c | 56 +++++++++++++++++++++++++++++++++----- libs/vkd3d/vkd3d_private.h | 2 +- 3 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 59859ad..31d793f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2920,7 +2920,7 @@ static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResour
desc = &resource_descs[0];
- if (FAILED(d3d12_resource_validate_desc(desc))) + if (FAILED(d3d12_resource_validate_desc(desc, device))) { WARN("Invalid resource desc.\n"); goto invalid; @@ -3226,7 +3226,7 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *i return; }
- if (FAILED(d3d12_resource_validate_desc(desc))) + if (FAILED(d3d12_resource_validate_desc(desc, device))) { WARN("Invalid resource desc.\n"); return; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index f5cdf4a..6e8c98e 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1001,7 +1001,7 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, HRESULT hr;
assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER); - assert(d3d12_resource_validate_desc(desc) == S_OK); + assert(d3d12_resource_validate_desc(desc, device) == S_OK);
if (!desc->MipLevels) { @@ -1591,8 +1591,45 @@ static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags) FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n"); }
-HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) +static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC *desc, + const struct vkd3d_format *format) { + uint64_t estimated_size; + + if (!desc->Alignment) + return true; + + if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT + && desc->Alignment != D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT + && (desc->SampleDesc.Count == 1 || desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)) + { + WARN("Invalid resource alignment %#"PRIx64".\n", desc->Alignment); + return false; + } + + if (desc->Alignment < D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT) + { + /* Windows uses the slice size to determine small alignment eligibility. DepthOrArraySize is ignored. */ + estimated_size = desc->Width * desc->Height * format->byte_count * format->block_byte_count + / (format->block_width * format->block_height); + if (estimated_size > D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT) + { + WARN("Invalid resource alignment %#"PRIx64" (required %#x).\n", + desc->Alignment, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); + return false; + } + } + + /* The size check for MSAA textures with D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT is probably + * not important. The 4MB requirement is no longer universal and Vulkan has no such requirement. */ + + return true; +} + +HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) +{ + const struct vkd3d_format *format; + switch (desc->Dimension) { case D3D12_RESOURCE_DIMENSION_BUFFER: @@ -1618,10 +1655,17 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) WARN("1D texture with a height of %u.\n", desc->Height); return E_INVALIDARG; } - break; - + /* Fall through. */ case D3D12_RESOURCE_DIMENSION_TEXTURE2D: case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0))) + { + WARN("Invalid format %#x.\n", desc->Format); + return E_INVALIDARG; + } + + if (!d3d12_resource_validate_texture_alignment(desc, format)) + return E_INVALIDARG; break;
default: @@ -1631,8 +1675,6 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc)
d3d12_validate_resource_flags(desc->Flags);
- /* FIXME: Validate alignment for textures. */ - return S_OK; }
@@ -1703,7 +1745,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->gpu_address = 0; resource->flags = 0;
- if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc))) + if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc, device))) return hr;
switch (desc->Dimension) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index df8d1a1..9ff6bba 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -435,7 +435,7 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour }
bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource) DECLSPEC_HIDDEN; -HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) DECLSPEC_HIDDEN; +HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) DECLSPEC_HIDDEN;
HRESULT d3d12_committed_resource_create(struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/resource.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 6e8c98e..825949b 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1591,6 +1591,29 @@ static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags) FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n"); }
+static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC *desc, + const struct vkd3d_format *format) +{ + if (!vkd3d_format_is_compressed(format)) + return true; + + if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D && format->block_height > 1) + { + WARN("1D texture with a format block height > 1.\n"); + return false; + } + + if (align(desc->Width, format->block_width) != desc->Width + || align(desc->Height, format->block_height) != desc->Height) + { + WARN("Invalid size %"PRIu64"x%u for block compressed format %#x.\n", + desc->Width, desc->Height, desc->Format); + return false; + } + + return true; +} + static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC *desc, const struct vkd3d_format *format) { @@ -1664,7 +1687,8 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d return E_INVALIDARG; }
- if (!d3d12_resource_validate_texture_alignment(desc, format)) + if (!d3d12_resource_validate_texture_format(desc, format) + || !d3d12_resource_validate_texture_alignment(desc, format)) return E_INVALIDARG; break;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 52de007..47c1649 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -1878,6 +1878,49 @@ static void test_create_committed_resource(void) &IID_ID3D12Resource, (void **)&resource); ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
+ heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; + resource_desc.Format = DXGI_FORMAT_BC1_UNORM; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == S_OK, "Failed to create committed resource, hr %#x.\n", hr); + ID3D12Resource_Release(resource); + + resource_desc.Height = 31; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + resource_desc.Width = 31; + resource_desc.Height = 32; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + resource_desc.Width = 30; + resource_desc.Height = 30; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + resource_desc.Width = 2; + resource_desc.Height = 2; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; + resource_desc.Width = 32; + resource_desc.Height = 1; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_COMMON, NULL, + &IID_ID3D12Resource, (void **)&resource); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + heap_properties.Type = D3D12_HEAP_TYPE_UPLOAD;
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com