d3d11:Implement deferred context resource and subresource methods Superseded

Revisions: 

Revision 1

user image Johannes Specht Author
31 Aug. 17

This implements all D3D11 deferred context (sub)resource methods. It fixes the textures issues in Crysis 3 (see https://bugs.winehq.org/show_bug.cgi?id=43635).

Single files Merged diff Tar archive
You have unsaved changes. Press CTRL + ENTER in a text field to submit your comments.

0001-d3d11-Implement-deferred-context-resource-and-subres.patch

From c2524adea3e22b65aa24f6513918ec33c38747c7 Mon Sep 17 00:00:00 2001
From: Johannes Specht <jojos_band@gmx.net>
Date: Thu, 31 Aug 2017 20:24:35 +0200
Subject: d3d11:Implement deferred context resource and subresource methods
---
dlls/d3d11/device.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 390 insertions(+), 10 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 15935b4e7aa..b81ad2434e7 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -40,6 +40,13 @@ enum deferred_cmd
DEFERRED_OMSETBLENDSTATE, /* blend_state_info */
DEFERRED_OMSETRENDERTARGETS, /* render_target_info */
+ DEFERRED_COPYRESOURCE, /* copy_resource_info */
+ DEFERRED_SETRESOURCEMINLOD, /* set_resource_min_lod_info */
+ DEFERRED_COPYSUBRESOURCEREGION, /* copy_subresource_region_info */
+ DEFERRED_UPDATESUBRESOURCE, /* update_subresource_info */
+ DEFERRED_RESOLVESUBRESOURCE, /* resolve_subresource_info */
+ DEFERRED_COPYSTRUCTURECOUNT, /* copy_structure_count_info */
+
DEFERRED_CSSETSHADER, /* cs_info */
DEFERRED_DSSETSHADER, /* ds_info */
DEFERRED_GSSETSHADER, /* gs_info */
@@ -140,6 +147,50 @@ struct deferred_call
ID3D11DepthStencilView *depth_stencil;
} render_target_info;
struct
+ {
+ ID3D11Resource *dst_resource;
+ ID3D11Resource *src_resource;
+ } copy_resource_info;
+ struct
+ {
+ ID3D11Resource *resource;
+ FLOAT min_lod;
+ } set_resource_min_lod_info;
+ struct
+ {
+ ID3D11Resource *dst_resource;
+ UINT dst_subresource_idx;
+ UINT dst_x;
+ UINT dst_y;
+ UINT dst_z;
+ ID3D11Resource *src_resource;
+ UINT src_subresource_idx;
+ D3D11_BOX *src_box;
+ } copy_subresource_region_info;
+ struct
+ {
+ ID3D11Resource *resource;
+ UINT subresource_idx;
+ D3D11_BOX *box;
+ void *data;
+ UINT row_pitch;
+ UINT depth_pitch;
+ } update_subresource_info;
+ struct
+ {
+ ID3D11Resource *dst_resource;
+ UINT dst_subresource_idx;
+ ID3D11Resource *src_resource;
+ UINT src_subresource_idx;
+ DXGI_FORMAT format;
+ } resolve_subresource_info;
+ struct
+ {
+ ID3D11Buffer *dst_buffer;
+ UINT dst_offset;
+ ID3D11UnorderedAccessView *src_view;
+ } copy_structure_count_info;
+ struct
{
ID3D11ComputeShader *shader;
/* FIXME: add class instances */
@@ -416,6 +467,50 @@ static void free_deferred_calls(struct list *commands)
ID3D11DepthStencilView_Release(call->render_target_info.depth_stencil);
break;
}
+ case DEFERRED_COPYRESOURCE:
+ {
+ if (call->copy_resource_info.dst_resource)
+ ID3D11Resource_Release(call->copy_resource_info.dst_resource);
+ if (call->copy_resource_info.src_resource)
+ ID3D11Resource_Release(call->copy_resource_info.src_resource);
+ break;
+ }
+ case DEFERRED_SETRESOURCEMINLOD:
+ {
+ if (call->set_resource_min_lod_info.resource)
+ ID3D11Resource_Release(call->set_resource_min_lod_info.resource);
+ break;
+ }
+ case DEFERRED_COPYSUBRESOURCEREGION:
+ {
+ if (call->copy_subresource_region_info.dst_resource)
+ ID3D11Resource_Release(call->copy_subresource_region_info.dst_resource);
+ if (call->copy_subresource_region_info.src_resource)
+ ID3D11Resource_Release(call->copy_subresource_region_info.src_resource);
+ break;
+ }
+ case DEFERRED_UPDATESUBRESOURCE:
+ {
+ if (call->update_subresource_info.resource)
+ ID3D11Resource_Release(call->update_subresource_info.resource);
+ break;
+ }
+ case DEFERRED_RESOLVESUBRESOURCE:
+ {
+ if (call->resolve_subresource_info.dst_resource)
+ ID3D11Resource_Release(call->resolve_subresource_info.dst_resource);
+ if (call->resolve_subresource_info.src_resource)
+ ID3D11Resource_Release(call->resolve_subresource_info.src_resource);
+ break;
+ }
+ case DEFERRED_COPYSTRUCTURECOUNT:
+ {
+ if (call->copy_structure_count_info.dst_buffer)
+ ID3D11Buffer_Release(call->copy_structure_count_info.dst_buffer);
+ if (call->copy_structure_count_info.src_view)
+ ID3D11UnorderedAccessView_Release(call->copy_structure_count_info.src_view);
+ break;
+ }
case DEFERRED_CSSETSHADER:
{
if (call->cs_info.shader)
@@ -613,6 +708,62 @@ static void exec_deferred_calls(ID3D11DeviceContext *iface, struct list *command
call->render_target_info.render_targets, call->render_target_info.depth_stencil);
break;
}
+ case DEFERRED_COPYRESOURCE:
+ {
+ ID3D11DeviceContext_CopyResource(iface,
+ call->copy_resource_info.dst_resource,
+ call->copy_resource_info.src_resource);
+ break;
+ }
+ case DEFERRED_SETRESOURCEMINLOD:
+ {
+ ID3D11DeviceContext_SetResourceMinLOD(iface,
+ call->set_resource_min_lod_info.resource,
+ call->set_resource_min_lod_info.min_lod);
+ break;
+ }
+ case DEFERRED_COPYSUBRESOURCEREGION:
+ {
+ ID3D11DeviceContext_CopySubresourceRegion(iface,
+ call->copy_subresource_region_info.dst_resource,
+ call->copy_subresource_region_info.dst_subresource_idx,
+ call->copy_subresource_region_info.dst_x,
+ call->copy_subresource_region_info.dst_y,
+ call->copy_subresource_region_info.dst_z,
+ call->copy_subresource_region_info.src_resource,
+ call->copy_subresource_region_info.src_subresource_idx,
+ call->copy_subresource_region_info.src_box);
+ break;
+ }
+ case DEFERRED_UPDATESUBRESOURCE:
+ {
+ ID3D11DeviceContext_UpdateSubresource(iface,
+ call->update_subresource_info.resource,
+ call->update_subresource_info.subresource_idx,
+ call->update_subresource_info.box,
+ call->update_subresource_info.data,
+ call->update_subresource_info.row_pitch,
+ call->update_subresource_info.depth_pitch);
+ break;
+ }
+ case DEFERRED_RESOLVESUBRESOURCE:
+ {
+ ID3D11DeviceContext_ResolveSubresource(iface,
+ call->resolve_subresource_info.dst_resource,
+ call->resolve_subresource_info.dst_subresource_idx,
+ call->resolve_subresource_info.src_resource,
+ call->resolve_subresource_info.src_subresource_idx,
+ call->resolve_subresource_info.format);
+ break;
+ }
+ case DEFERRED_COPYSTRUCTURECOUNT:
+ {
+ ID3D11DeviceContext_CopyStructureCount(iface,
+ call->copy_structure_count_info.dst_buffer,
+ call->copy_structure_count_info.dst_offset,
+ call->copy_structure_count_info.src_view);
+ break;
+ }
case DEFERRED_CSSETSHADER:
{
ID3D11DeviceContext_CSSetShader(iface, call->cs_info.shader, NULL, 0);
@@ -4334,31 +4485,234 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_CopySubresourceRegion(ID3D1
ID3D11Resource *dst_resource, UINT dst_subresource_idx, UINT dst_x, UINT dst_y, UINT dst_z,
ID3D11Resource *src_resource, UINT src_subresource_idx, const D3D11_BOX *src_box)
{
- FIXME("iface %p, dst_resource %p, dst_subresource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
- "src_resource %p, src_subresource_idx %u, src_box %p stub!\n",
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ TRACE("iface %p, dst_resource %p, dst_subresource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
+ "src_resource %p, src_subresource_idx %u, src_box %p.\n",
iface, dst_resource, dst_subresource_idx, dst_x, dst_y, dst_z,
src_resource, src_subresource_idx, src_box);
+
+ if (!(call = add_deferred_call(context, sizeof(D3D11_BOX))))
+ return;
+
+ if (dst_resource) ID3D11Resource_AddRef(dst_resource);
+ if (src_resource) ID3D11Resource_AddRef(src_resource);
+
+ call->cmd = DEFERRED_COPYSUBRESOURCEREGION;
+ call->copy_subresource_region_info.dst_resource = dst_resource;
+ call->copy_subresource_region_info.dst_subresource_idx = dst_subresource_idx;
+ call->copy_subresource_region_info.dst_x = dst_x;
+ call->copy_subresource_region_info.dst_y = dst_y;
+ call->copy_subresource_region_info.dst_z = dst_z;
+ call->copy_subresource_region_info.src_resource = src_resource;
+ call->copy_subresource_region_info.src_subresource_idx = src_subresource_idx;
+ if (src_box)
+ {
+ call->copy_subresource_region_info.src_box = (void *)(call + 1);
+ *call->copy_subresource_region_info.src_box = *src_box;
+ }
+ else
+ {
+ call->copy_subresource_region_info.src_box = NULL;
+ }
}
static void STDMETHODCALLTYPE d3d11_deferred_context_CopyResource(ID3D11DeviceContext *iface,
ID3D11Resource *dst_resource, ID3D11Resource *src_resource)
{
- FIXME("iface %p, dst_resource %p, src_resource %p stub!\n", iface, dst_resource, src_resource);
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ TRACE("iface %p, dst_resource %p, src_resource %p.\n", iface, dst_resource, src_resource);
+
+ if (!(call = add_deferred_call(context, 0)))
+ return;
+
+ if (dst_resource) ID3D11Resource_AddRef(dst_resource);
+ if (src_resource) ID3D11Resource_AddRef(src_resource);
+
+ call->cmd = DEFERRED_COPYRESOURCE;
+ call->copy_resource_info.dst_resource = dst_resource;
+ call->copy_resource_info.src_resource = src_resource;
}
+/*
+ * Notes:
+ * - Uncertain whether the box specifies coordinates before or after
+ * down-scaling by mipmapping (assumed before).
+ * - Uncertain whether row_pitch is set for 1D textures this that
+ * row_pitch equals the number of bytes at *data (assumed it is).
+ */
static void STDMETHODCALLTYPE d3d11_deferred_context_UpdateSubresource(ID3D11DeviceContext *iface,
ID3D11Resource *resource, UINT subresource_idx, const D3D11_BOX *box,
const void *data, UINT row_pitch, UINT depth_pitch)
{
- FIXME("iface %p, resource %p, subresource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u stub!\n",
- iface, resource, subresource_idx, box, data, row_pitch, depth_pitch);
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ D3D11_RESOURCE_DIMENSION resource_dimension;
+ D3D11_BUFFER_DESC buffer_desc;
+ D3D11_TEXTURE1D_DESC texture1d_desc;
+ D3D11_TEXTURE2D_DESC texture2d_desc;
+ D3D11_TEXTURE3D_DESC texture3d_desc;
+
+ UINT width,height,depth; /* Size of a 1D, 2D, or 3D texture (in texels).*/
+ UINT mip_map_level; /* The mipmaping level, 0 is the most detailed*/
+ UINT data_byte_count; /* Number of bytes to copy */
+
+ TRACE("iface %p, resource %p, subresource_idx %u, box %p, data %p, row_pitch %u, depth_pitch %u.\n",
+ iface, resource, subresource_idx, box, data, row_pitch, depth_pitch);
+
+ /* Mute compiler warnings */
+ width = 0; height = 0; depth = 0;
+ data_byte_count = 0;
+
+ ID3D11Resource_GetType(resource,&resource_dimension);
+ /* Determine dimensioning of destination texture (without mipmapping, etc.),
+ * setup the correct descriptor, and bailout for unknown resource types.*/
+ if (box)
+ {
+ width = box->bottom - box->top;
+ height = box->right - box->left;
+ depth = box->back - box->front;
+ } else {
+ switch (resource_dimension)
+ {
+ case D3D11_RESOURCE_DIMENSION_BUFFER:
+ {
+ /* No texture ...*/
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ ID3D11Texture1D_GetDesc((ID3D11Texture1D *)resource,&texture1d_desc);
+ width = texture1d_desc.Width;
+ height = 1;
+ depth = 1;
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ ID3D11Texture2D_GetDesc((ID3D11Texture2D *)resource,&texture2d_desc);
+ width = texture2d_desc.Width;
+ height = texture2d_desc.Height;
+ depth = 1;
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ ID3D11Texture3D_GetDesc((ID3D11Texture3D *)resource,&texture3d_desc);
+ width = texture3d_desc.Width;
+ height = texture3d_desc.Height;
+ depth = texture3d_desc.Depth;
+ break;
+ }
+ default:
+ {
+ ERR("Unknown resource type %u!\n",resource_dimension);
+ return;
+ }
+ }
+ }
+
+ /* Calculate the number of bytes to copy, taking arrays,
+ * mipmapping and block compression into account*/
+ switch (resource_dimension)
+ {
+ case D3D11_RESOURCE_DIMENSION_BUFFER:
+ {
+ data_byte_count = buffer_desc.ByteWidth;
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
+ {
+ mip_map_level = subresource_idx % texture1d_desc.MipLevels;
+ width = max(1,width >> mip_map_level);
+
+ data_byte_count = row_pitch;
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
+ {
+ mip_map_level = subresource_idx % texture2d_desc.MipLevels;
+ width = max(1,width >> mip_map_level);
+ height = max(1,height >> mip_map_level);
+
+ data_byte_count = height * row_pitch;
+
+ /* 4x4 texel block compression (i.e., a "row" contains 4 texel rows),
+ * include partially used blocks in the last row if the height
+ * is not an integer multiple of 4*/
+ if ((texture2d_desc.Format >= DXGI_FORMAT_BC1_TYPELESS && texture2d_desc.Format <= DXGI_FORMAT_BC5_SNORM) ||
+ (texture2d_desc.Format >= DXGI_FORMAT_BC6H_TYPELESS && texture2d_desc.Format <= DXGI_FORMAT_BC7_UNORM_SRGB))
+ {
+ data_byte_count = (data_byte_count +
+ ((height % 4) ? row_pitch : 0)
+ ) >> 2;
+ }
+
+ break;
+ }
+ case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
+ {
+ mip_map_level = subresource_idx % texture3d_desc.MipLevels;
+ width = max(1,width >> mip_map_level);
+ height = max(1,height >> mip_map_level);
+ depth = max(1,depth >> mip_map_level);
+
+ data_byte_count = depth * depth_pitch;
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!(call = add_deferred_call(context, sizeof(D3D11_BOX)+data_byte_count)))
+ return;
+
+ if (resource) ID3D11Resource_AddRef(resource);
+
+ call->cmd = DEFERRED_UPDATESUBRESOURCE;
+ call->update_subresource_info.resource = resource;
+ call->update_subresource_info.subresource_idx = subresource_idx;
+ call->update_subresource_info.row_pitch = row_pitch;
+ call->update_subresource_info.depth_pitch = depth_pitch;
+
+ if (box)
+ {
+ call->update_subresource_info.box = (void *)(call + 1);
+ call->update_subresource_info.data = (void *)(call->update_subresource_info.box + 1);
+ *call->update_subresource_info.box = *box;
+ }
+ else
+ {
+ call->update_subresource_info.box = NULL;
+ call->update_subresource_info.data = (void *)(call + 1);
+ }
+ memcpy(call->update_subresource_info.data, data, data_byte_count);
}
static void STDMETHODCALLTYPE d3d11_deferred_context_CopyStructureCount(ID3D11DeviceContext *iface,
ID3D11Buffer *dst_buffer, UINT dst_offset, ID3D11UnorderedAccessView *src_view)
{
- FIXME("iface %p, dst_buffer %p, dst_offset %u, src_view %p stub!\n",
- iface, dst_buffer, dst_offset, src_view);
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ TRACE("iface %p, dst_buffer %p, dst_offset %u, src_view %p.\n",
+ iface, dst_buffer, dst_offset, src_view);
+
+ if (!(call = add_deferred_call(context, 0)))
+ return;
+
+ if (dst_buffer) ID3D11Buffer_AddRef(dst_buffer);
+ if (src_view) ID3D11UnorderedAccessView_AddRef(src_view);
+
+ call->cmd = DEFERRED_COPYSTRUCTURECOUNT;
+ call->copy_structure_count_info.dst_buffer = dst_buffer;
+ call->copy_structure_count_info.dst_offset = dst_offset;
+ call->copy_structure_count_info.src_view = src_view;
}
static void STDMETHODCALLTYPE d3d11_deferred_context_ClearRenderTargetView(ID3D11DeviceContext *iface,
@@ -4424,7 +4778,18 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_GenerateMips(ID3D11DeviceCo
static void STDMETHODCALLTYPE d3d11_deferred_context_SetResourceMinLOD(ID3D11DeviceContext *iface,
ID3D11Resource *resource, FLOAT min_lod)
{
- FIXME("iface %p, resource %p, min_lod %f stub!\n", iface, resource, min_lod);
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ TRACE("iface %p, resource %p, min_lod %f.\n", iface, resource, min_lod);
+
+ if (!(call = add_deferred_call(context, 0)))
+ return;
+
+ call->cmd = DEFERRED_SETRESOURCEMINLOD;
+ if (resource) ID3D11Resource_AddRef(resource);
+ call->set_resource_min_lod_info.resource = resource;
+ call->set_resource_min_lod_info.min_lod = min_lod;
}
static FLOAT STDMETHODCALLTYPE d3d11_deferred_context_GetResourceMinLOD(ID3D11DeviceContext *iface,
@@ -4440,10 +4805,25 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_ResolveSubresource(ID3D11De
ID3D11Resource *src_resource, UINT src_subresource_idx,
DXGI_FORMAT format)
{
- FIXME("iface %p, dst_resource %p, dst_subresource_idx %u, src_resource %p, src_subresource_idx %u, "
- "format %s stub!\n",
+ struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+ struct deferred_call *call;
+
+ TRACE("iface %p, dst_resource %p, dst_subresource_idx %u, src_resource %p, src_subresource_idx %u, "
+ "format %s.\n",
iface, dst_resource, dst_subresource_idx, src_resource, src_subresource_idx,
debug_dxgi_format(format));
+
+ if (!(call = add_deferred_call(context, 0)))
+ return;
+
+ call->cmd = DEFERRED_RESOLVESUBRESOURCE;
+ if (dst_resource) ID3D11Resource_AddRef(dst_resource);
+ if (src_resource) ID3D11Resource_AddRef(src_resource);
+ call->resolve_subresource_info.dst_resource = dst_resource;
+ call->resolve_subresource_info.dst_subresource_idx = dst_subresource_idx;
+ call->resolve_subresource_info.src_resource = src_resource;
+ call->resolve_subresource_info.src_subresource_idx = src_subresource_idx;
+ call->resolve_subresource_info.format = format;
}
static void STDMETHODCALLTYPE d3d11_deferred_context_ExecuteCommandList(ID3D11DeviceContext *iface,
--
2.14.1