[PATCH v3 7/7] wined3d: Handle typeless resolve in the FBO blitter.
Jan Sikorski
jsikorski at codeweavers.com
Wed Mar 31 05:27:40 CDT 2021
Avoid resolving source texture before the blit due to format conversion in that case.
Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
dlls/d3d10core/tests/d3d10core.c | 12 +--
dlls/d3d11/tests/d3d11.c | 12 +--
dlls/wined3d/surface.c | 12 ++-
dlls/wined3d/texture.c | 127 ++++++++++++++++++++++++++++++-
4 files changed, 145 insertions(+), 18 deletions(-)
diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c
index c24ef326cf1..9d10080ffc0 100644
--- a/dlls/d3d10core/tests/d3d10core.c
+++ b/dlls/d3d10core/tests/d3d10core.c
@@ -18065,22 +18065,22 @@ static void test_multisample_resolve(void)
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
@@ -18117,12 +18117,12 @@ static void test_multisample_resolve(void)
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM,
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 91637df0747..0819f8198c4 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -30330,22 +30330,22 @@ static void test_multisample_resolve(void)
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
@@ -30382,12 +30382,12 @@ static void test_multisample_resolve(void)
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &green, 0xffbcffbc, TRUE},
+ &green, 0xffbcffbc},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- &color, 0xfff1e1cf, TRUE},
+ &color, 0xfff1e1cf},
{DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_TYPELESS,
DXGI_FORMAT_R8G8B8A8_UNORM,
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 4a438f048d6..c5d7a7d9d55 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1482,12 +1482,12 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource;
struct wined3d_device *device = dst_texture->resource.device;
struct wined3d_swapchain *src_swapchain, *dst_swapchain;
+ BOOL scale, convert, resolve, resolve_typeless = FALSE;
const struct wined3d_format *resolve_format = NULL;
const struct wined3d_color_key *colour_key = NULL;
DWORD src_location, dst_location, valid_locations;
struct wined3d_context *context;
enum wined3d_blit_op blit_op;
- BOOL scale, convert, resolve;
RECT src_rect, dst_rect;
bool src_ds, dst_ds;
@@ -1566,6 +1566,14 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
|| src_box->bottom - src_box->top != dst_box->bottom - dst_box->top;
convert = src_texture->resource.format->id != dst_texture->resource.format->id;
resolve = src_texture->resource.multisample_type != dst_texture->resource.multisample_type;
+ if (resolve)
+ {
+ resolve_typeless = (wined3d_format_is_typeless(src_texture->resource.format)
+ || wined3d_format_is_typeless(dst_texture->resource.format))
+ && (src_texture->resource.format->typeless_id == dst_texture->resource.format->typeless_id);
+ if (resolve_typeless && !resolve_format)
+ WARN("Resolve format for typeless resolve not specified.\n");
+ }
dst_ds = dst_texture->resource.format->depth_size || dst_texture->resource.format->stencil_size;
src_ds = src_texture->resource.format->depth_size || src_texture->resource.format->stencil_size;
@@ -1704,7 +1712,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
context = context_acquire(device, dst_texture, dst_sub_resource_idx);
- if (src_texture->resource.multisample_type != WINED3D_MULTISAMPLE_NONE
+ if (src_texture->resource.multisample_type != WINED3D_MULTISAMPLE_NONE && !resolve_typeless
&& ((scale && !context->d3d_info->scaled_resolve)
|| convert || !wined3d_is_colour_blit(blit_op)))
src_location = WINED3D_LOCATION_RB_RESOLVED;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index af3aa003f1d..f4397947a89 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -322,11 +322,12 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location,
const RECT *dst_rect, const struct wined3d_format *resolve_format)
{
- struct wined3d_texture *required_texture, *restore_texture;
+ struct wined3d_texture *required_texture, *restore_texture, *dst_save_texture = dst_texture;
+ unsigned int restore_idx, dst_save_sub_resource_idx = dst_sub_resource_idx;
+ struct wined3d_texture *src_staging_texture = NULL;
const struct wined3d_gl_info *gl_info;
struct wined3d_context_gl *context_gl;
- unsigned int restore_idx;
- bool scaled_resolve;
+ bool resolve, scaled_resolve;
GLenum gl_filter;
GLenum buffer;
RECT s, d;
@@ -337,7 +338,8 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture,
dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect), resolve_format);
- scaled_resolve = wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location)
+ resolve = wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location);
+ scaled_resolve = resolve
&& (abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top)
|| abs(src_rect->right - src_rect->left) != abs(dst_rect->right - dst_rect->left));
@@ -346,6 +348,108 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
else
gl_filter = scaled_resolve ? GL_SCALED_RESOLVE_FASTEST_EXT : GL_NEAREST;
+ if (resolve)
+ {
+ GLint resolve_internal, src_internal, dst_internal;
+ enum wined3d_format_id resolve_format_id;
+
+ src_internal = wined3d_gl_get_internal_format(&src_texture->resource,
+ wined3d_format_gl(src_texture->resource.format), src_location == WINED3D_LOCATION_TEXTURE_SRGB);
+ dst_internal = wined3d_gl_get_internal_format(&dst_texture->resource,
+ wined3d_format_gl(dst_texture->resource.format), dst_location == WINED3D_LOCATION_TEXTURE_SRGB);
+
+ if (resolve_format)
+ {
+ resolve_internal = wined3d_format_gl(resolve_format)->internal;
+ resolve_format_id = resolve_format->id;
+ }
+ else if (!wined3d_format_is_typeless(src_texture->resource.format))
+ {
+ resolve_internal = src_internal;
+ resolve_format_id = src_texture->resource.format->id;
+ }
+ else
+ {
+ resolve_internal = dst_internal;
+ resolve_format_id = dst_texture->resource.format->id;
+ }
+
+ /* In case of typeless resolve the texture type may not match the resolve type.
+ * To handle that, allocate intermediate texture(s) to resolve from/to.
+ * A possible performance improvement would be to resolve using a shader instead. */
+ if (src_internal != resolve_internal)
+ {
+ struct wined3d_resource_desc desc;
+ unsigned src_level;
+ HRESULT hr;
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+ desc.format = resolve_format_id;
+ desc.multisample_type = src_texture->resource.multisample_type;
+ desc.multisample_quality = src_texture->resource.multisample_quality;
+ desc.usage = WINED3DUSAGE_PRIVATE;
+ desc.bind_flags = 0;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+ desc.width = wined3d_texture_get_level_width(src_texture, src_level);
+ desc.height = wined3d_texture_get_level_height(src_texture, src_level);
+ desc.depth = 1;
+ desc.size = 0;
+
+ hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops,
+ &src_staging_texture);
+ if (FAILED(hr))
+ {
+ ERR("Failed to create staging texture, hr %#x.\n", hr);
+ return;
+ }
+
+ if (src_location == WINED3D_LOCATION_DRAWABLE)
+ FIXME("WINED3D_LOCATION_DRAWABLE not supported for the source of a typeless resolve.");
+
+ device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_RAW_BLIT, context,
+ src_texture, src_sub_resource_idx, src_location, src_rect,
+ src_staging_texture, 0, src_location, src_rect,
+ NULL, WINED3D_TEXF_NONE, NULL);
+
+ src_texture = src_staging_texture;
+ src_sub_resource_idx = 0;
+ }
+
+ if (dst_internal != resolve_internal)
+ {
+ struct wined3d_resource_desc desc;
+ unsigned dst_level;
+ HRESULT hr;
+
+ dst_level = dst_sub_resource_idx % dst_texture->level_count;
+ desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
+ desc.format = resolve_format_id;
+ desc.multisample_type = dst_texture->resource.multisample_type;
+ desc.multisample_quality = dst_texture->resource.multisample_quality;
+ desc.usage = WINED3DUSAGE_PRIVATE;
+ desc.bind_flags = 0;
+ desc.access = WINED3D_RESOURCE_ACCESS_GPU;
+ desc.width = wined3d_texture_get_level_width(dst_texture, dst_level);
+ desc.height = wined3d_texture_get_level_height(dst_texture, dst_level);
+ desc.depth = 1;
+ desc.size = 0;
+
+ hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops,
+ &dst_texture);
+ if (FAILED(hr))
+ {
+ ERR("Failed to create staging texture, hr %#x.\n", hr);
+ if (src_staging_texture)
+ wined3d_texture_decref(src_staging_texture);
+ return;
+ }
+
+ wined3d_texture_load_location(dst_texture, 0, context, dst_location);
+ dst_sub_resource_idx = 0;
+ }
+ }
+
/* Make sure the locations are up-to-date. Loading the destination
* surface isn't required if the entire surface is overwritten. (And is
* in fact harmful if we're being called by surface_load_location() with
@@ -437,6 +541,21 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont
if (dst_location == WINED3D_LOCATION_DRAWABLE && dst_texture->swapchain->front_buffer == dst_texture)
gl_info->gl_ops.gl.p_glFlush();
+ if (dst_texture != dst_save_texture)
+ {
+ if (dst_location == WINED3D_LOCATION_DRAWABLE)
+ FIXME("WINED3D_LOCATION_DRAWABLE not supported for the destination of a typeless resolve.");
+
+ device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_RAW_BLIT, context,
+ dst_texture, 0, dst_location, dst_rect,
+ dst_save_texture, dst_save_sub_resource_idx, dst_location, dst_rect,
+ NULL, WINED3D_TEXF_NONE, NULL);
+ wined3d_texture_decref(dst_texture);
+ }
+
+ if (src_staging_texture)
+ wined3d_texture_decref(src_staging_texture);
+
if (restore_texture)
context_restore(context, restore_texture, restore_idx);
}
--
2.31.0
More information about the wine-devel
mailing list