[PATCH 2/6] wined3d: Keep track of FBOs through the GL names (v3).
Stefan Dösinger
stefandoesinger at gmx.at
Sun Feb 21 15:29:57 CST 2016
Version 2: Don't use fbo_entry->d3d_* for logging, plan for it to go
away. The disadvantage is now that we don't know the d3d properties once
we find out that an FBO doesn't work and need a full TRACE log for this
information, but I think that's something we can live with.
If there is a prettier way to find the texture target of a GL texture
name please advise. I couldn't find any.
Version 3:
*) Memset only struct wined3d_fbo_entry_key, not the entire fbo_entry
struct. I guess I could only memset up to the first object to catch the
potential alignment gap between rb_namespace and the object array, but
it seems cleaner to memset the entire structure.
*) Explicitly enumerate all possible GL attachments for the debug
strings instead of using sprintf.
*) Rename context_generate_fbo_key and the render target count
parameter, remove the inline.
*) Make the empty resource static const.
Signed-off-by: Stefan Dösinger <stefandoesinger at gmx.at>
---
dlls/wined3d/context.c | 280 +++++++++++++++++++++++++----------------
dlls/wined3d/wined3d_private.h | 17 ++-
2 files changed, 186 insertions(+), 111 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 3668195..6862fe3 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -120,57 +120,39 @@ static void context_attach_depth_stencil_rb(const struct wined3d_gl_info *gl_inf
/* Context activation is done by the caller. */
static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
- GLenum fbo_target, struct wined3d_surface *depth_stencil, DWORD location)
+ GLenum fbo_target, const struct wined3d_fbo_resource *resource, BOOL rb_namespace,
+ DWORD format_flags, GLuint rb_override)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
- TRACE("Attach depth stencil %p\n", depth_stencil);
-
- if (depth_stencil)
+ if (resource->object)
{
- DWORD format_flags = depth_stencil->container->resource.format_flags;
+ TRACE("Attach depth stencil %u.\n", resource->object);
- if (depth_stencil->current_renderbuffer)
+ if (rb_override)
{
context_attach_depth_stencil_rb(gl_info, fbo_target,
- format_flags, depth_stencil->current_renderbuffer->id);
+ format_flags, rb_override);
+ }
+ else if (rb_namespace)
+ {
+ context_attach_depth_stencil_rb(gl_info, fbo_target,
+ format_flags, resource->object);
}
else
{
- switch (location)
+ if (format_flags & WINED3DFMT_FLAG_DEPTH)
{
- case WINED3D_LOCATION_TEXTURE_RGB:
- case WINED3D_LOCATION_TEXTURE_SRGB:
- if (format_flags & WINED3DFMT_FLAG_DEPTH)
- {
- gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
- depth_stencil->texture_target, depth_stencil->container->texture_rgb.name,
- depth_stencil->texture_level);
- checkGLcall("glFramebufferTexture2D()");
- }
-
- if (format_flags & WINED3DFMT_FLAG_STENCIL)
- {
- gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
- depth_stencil->texture_target, depth_stencil->container->texture_rgb.name,
- depth_stencil->texture_level);
- checkGLcall("glFramebufferTexture2D()");
- }
- break;
-
- case WINED3D_LOCATION_RB_MULTISAMPLE:
- context_attach_depth_stencil_rb(gl_info, fbo_target,
- format_flags, depth_stencil->rb_multisample);
- break;
-
- case WINED3D_LOCATION_RB_RESOLVED:
- context_attach_depth_stencil_rb(gl_info, fbo_target,
- format_flags, depth_stencil->rb_resolved);
- break;
+ gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
+ resource->target, resource->object, resource->level);
+ checkGLcall("glFramebufferTexture2D()");
+ }
- default:
- ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location);
- break;
+ if (format_flags & WINED3DFMT_FLAG_STENCIL)
+ {
+ gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
+ resource->target, resource->object, resource->level);
+ checkGLcall("glFramebufferTexture2D()");
}
}
@@ -188,6 +170,8 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
}
else
{
+ TRACE("Attach depth stencil 0.\n");
+
gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
checkGLcall("glFramebufferTexture2D()");
@@ -198,42 +182,26 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
/* Context activation is done by the caller. */
static void context_attach_surface_fbo(struct wined3d_context *context,
- GLenum fbo_target, DWORD idx, struct wined3d_surface *surface, DWORD location)
+ GLenum fbo_target, DWORD idx, const struct wined3d_fbo_resource *resource, BOOL rb_namespace)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
- TRACE("Attach surface %p to %u\n", surface, idx);
+ TRACE("Attach GL object %u to %u.\n", resource->object, idx);
- if (surface && surface->resource.format->id != WINED3DFMT_NULL)
+ if (resource->object)
{
- BOOL srgb;
- switch (location)
+ if (rb_namespace)
{
- case WINED3D_LOCATION_TEXTURE_RGB:
- case WINED3D_LOCATION_TEXTURE_SRGB:
- srgb = location == WINED3D_LOCATION_TEXTURE_SRGB;
- gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
- surface->texture_target, surface_get_texture_name(surface, context, srgb),
- surface->texture_level);
- checkGLcall("glFramebufferTexture2D()");
- break;
-
- case WINED3D_LOCATION_RB_MULTISAMPLE:
- gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
- GL_RENDERBUFFER, surface->rb_multisample);
- checkGLcall("glFramebufferRenderbuffer()");
- break;
-
- case WINED3D_LOCATION_RB_RESOLVED:
- gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
- GL_RENDERBUFFER, surface->rb_resolved);
- checkGLcall("glFramebufferRenderbuffer()");
- break;
-
- default:
- ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location);
- break;
+ gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+ GL_RENDERBUFFER, resource->object);
+ checkGLcall("glFramebufferRenderbuffer()");
+ }
+ else
+ {
+ gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+ resource->target, resource->object, resource->level);
+ checkGLcall("glFramebufferTexture2D()");
}
}
else
@@ -377,19 +345,76 @@ static inline DWORD context_generate_rt_mask_from_surface(const struct wined3d_s
return (1u << 31) | surface_get_gl_buffer(target);
}
+static inline void context_set_fbo_key_for_surface(const struct wined3d_context *context,
+ struct wined3d_fbo_entry_key *key, UINT idx, struct wined3d_surface *surface,
+ DWORD location)
+{
+ if (!surface)
+ {
+ key->objects[idx].object = 0;
+ key->objects[idx].level = key->objects[idx].target = 0;
+ }
+ else
+ {
+ switch (location)
+ {
+ case WINED3D_LOCATION_TEXTURE_RGB:
+ key->objects[idx].object = surface_get_texture_name(surface, context, FALSE);
+ key->objects[idx].level = surface->texture_level;
+ key->objects[idx].target = surface->texture_target;
+ break;
+
+ case WINED3D_LOCATION_TEXTURE_SRGB:
+ key->objects[idx].object = surface_get_texture_name(surface, context, TRUE);
+ key->objects[idx].level = surface->texture_level;
+ key->objects[idx].target = surface->texture_target;
+ break;
+
+ case WINED3D_LOCATION_RB_MULTISAMPLE:
+ key->objects[idx].object = surface->rb_multisample;
+ key->objects[idx].level = key->objects[idx].target = 0;
+ key->rb_namespace |= 1 << idx;
+ break;
+
+ case WINED3D_LOCATION_RB_RESOLVED:
+ key->objects[idx].object = surface->rb_resolved;
+ key->objects[idx].level = key->objects[idx].target = 0;
+ key->rb_namespace |= 1 << idx;
+ break;
+ }
+ }
+}
+
+static void context_generate_fbo_key(const struct wined3d_context *context,
+ struct wined3d_fbo_entry_key *key, struct wined3d_surface **render_targets,
+ struct wined3d_surface *depth_stencil, DWORD color_location,
+ DWORD ds_location)
+{
+ UINT i;
+
+ key->rb_namespace = 0;
+ context_set_fbo_key_for_surface(context, key, 0, depth_stencil, ds_location);
+
+ for (i = 0; i < context->gl_info->limits.buffers; ++i)
+ context_set_fbo_key_for_surface(context, key, i + 1, render_targets[i], color_location);
+}
+
static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context,
struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil,
DWORD color_location, DWORD ds_location)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
struct fbo_entry *entry;
-
- entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
- entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets));
- memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
- entry->depth_stencil = depth_stencil;
- entry->color_location = color_location;
- entry->ds_location = ds_location;
+ UINT object_count = gl_info->limits.buffers + 1;
+
+ entry = HeapAlloc(GetProcessHeap(), 0,
+ FIELD_OFFSET(struct fbo_entry, key.objects[object_count]));
+ entry->d3d_render_targets = HeapAlloc(GetProcessHeap(), 0,
+ gl_info->limits.buffers * sizeof(*entry->d3d_render_targets));
+ memset(&entry->key, 0, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count]));
+ context_generate_fbo_key(context, &entry->key, render_targets, depth_stencil, color_location, ds_location);
+ memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers);
+ entry->d3d_depth_stencil = depth_stencil;
entry->rt_mask = context_generate_rt_mask(GL_COLOR_ATTACHMENT0);
entry->attached = FALSE;
gl_info->fbo_ops.glGenFramebuffers(1, &entry->id);
@@ -409,10 +434,9 @@ static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum targ
context_bind_fbo(context, target, entry->id);
context_clean_fbo_attachments(gl_info, target);
- memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
- entry->depth_stencil = depth_stencil;
- entry->color_location = color_location;
- entry->ds_location = ds_location;
+ context_generate_fbo_key(context, &entry->key, render_targets, depth_stencil, color_location, ds_location);
+ memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers);
+ entry->d3d_depth_stencil = depth_stencil;
entry->attached = FALSE;
}
@@ -426,7 +450,7 @@ static void context_destroy_fbo_entry(struct wined3d_context *context, struct fb
}
--context->fbo_entry_count;
list_remove(&entry->entry);
- HeapFree(GetProcessHeap(), 0, entry->render_targets);
+ HeapFree(GetProcessHeap(), 0, entry->d3d_render_targets);
HeapFree(GetProcessHeap(), 0, entry);
}
@@ -437,6 +461,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
{
const struct wined3d_gl_info *gl_info = context->gl_info;
struct fbo_entry *entry;
+ UINT object_count = gl_info->limits.buffers + 1;
+ unsigned int i;
if (depth_stencil && render_targets && render_targets[0])
{
@@ -448,19 +474,44 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
}
}
- LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
+ context_generate_fbo_key(context, context->fbo_key, render_targets, depth_stencil, color_location,
+ ds_location);
+
+ if (TRACE_ON(d3d))
{
- if (!memcmp(entry->render_targets,
- render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets))
- && entry->depth_stencil == depth_stencil && entry->color_location == color_location
- && entry->ds_location == ds_location)
+ TRACE("Dumping FBO attachments:\n");
+ for (i = 0; i < gl_info->limits.buffers; ++i)
{
- list_remove(&entry->entry);
- list_add_head(&context->fbo_list, &entry->entry);
- return entry;
+ if (render_targets[i])
+ {
+ TRACE("\tColor attachment %u: (%p) %s gl obj %u(%s) %ux%u %u samples.\n",
+ i, render_targets[i], debug_d3dformat(render_targets[i]->resource.format->id),
+ context->fbo_key->objects[i + 1].object,
+ context->fbo_key->rb_namespace & (1 << (i + 1)) ? "rb" : "texure",
+ render_targets[i]->pow2Width, render_targets[i]->pow2Height,
+ render_targets[i]->resource.multisample_type);
+ }
+ }
+ if (depth_stencil)
+ {
+ TRACE("\tDepth attachment: (%p) %s gl obj %u(%s) %ux%u %u samples.\n",
+ depth_stencil, debug_d3dformat(depth_stencil->resource.format->id),
+ context->fbo_key->objects[0].object,
+ context->fbo_key->rb_namespace & (1 << 0) ? "rb" : "texure",
+ depth_stencil->pow2Width, depth_stencil->pow2Height, depth_stencil->resource.multisample_type);
}
}
+ LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
+ {
+ if (memcmp(context->fbo_key, &entry->key, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count])))
+ continue;
+
+ list_remove(&entry->entry);
+ list_add_head(&context->fbo_list, &entry->entry);
+ return entry;
+ }
+
if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES)
{
entry = context_create_fbo_entry(context, render_targets, depth_stencil, color_location, ds_location);
@@ -484,7 +535,7 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
const struct wined3d_gl_info *gl_info = context->gl_info;
unsigned int i;
GLuint read_binding, draw_binding;
- struct wined3d_surface *depth_stencil = entry->depth_stencil;
+ struct wined3d_surface *depth_stencil = entry->d3d_depth_stencil;
if (entry->attached)
{
@@ -499,25 +550,36 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
/* Apply render targets */
for (i = 0; i < gl_info->limits.buffers; ++i)
{
- context_attach_surface_fbo(context, target, i, entry->render_targets[i], entry->color_location);
+ context_attach_surface_fbo(context, target, i, &entry->key.objects[i + 1],
+ entry->key.rb_namespace & (1 << (i + 1)));
}
- if (depth_stencil && entry->render_targets[0]
+ if (depth_stencil && entry->d3d_render_targets[0]
&& (depth_stencil->resource.multisample_type
- != entry->render_targets[0]->resource.multisample_type
+ != entry->d3d_render_targets[0]->resource.multisample_type
|| depth_stencil->resource.multisample_quality
- != entry->render_targets[0]->resource.multisample_quality))
+ != entry->d3d_render_targets[0]->resource.multisample_quality))
{
WARN("Color multisample type %u and quality %u, depth stencil has %u and %u, disabling ds buffer.\n",
- entry->render_targets[0]->resource.multisample_quality,
- entry->render_targets[0]->resource.multisample_type,
+ entry->d3d_render_targets[0]->resource.multisample_quality,
+ entry->d3d_render_targets[0]->resource.multisample_type,
depth_stencil->resource.multisample_quality, depth_stencil->resource.multisample_type);
depth_stencil = NULL;
}
if (depth_stencil)
- surface_set_compatible_renderbuffer(depth_stencil, entry->render_targets[0]);
- context_attach_depth_stencil_fbo(context, target, depth_stencil, entry->ds_location);
+ {
+ DWORD format_flags = depth_stencil->container->resource.format_flags;
+ surface_set_compatible_renderbuffer(depth_stencil, entry->d3d_render_targets[0]);
+ context_attach_depth_stencil_fbo(context, target, &entry->key.objects[0],
+ entry->key.rb_namespace & 0x1, format_flags,
+ depth_stencil->current_renderbuffer ? depth_stencil->current_renderbuffer->id : 0);
+ }
+ else
+ {
+ static const struct wined3d_fbo_resource resource = {0};
+ context_attach_depth_stencil_fbo(context, target, &resource, FALSE, 0, 0);
+ }
/* Set valid read and draw buffer bindings to satisfy pedantic pre-ES2_compatibility
* GL contexts requirements. */
@@ -766,7 +828,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device
{
UINT j;
- if (entry->depth_stencil == surface)
+ if (entry->d3d_depth_stencil == surface)
{
callback(context, entry);
continue;
@@ -774,7 +836,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device
for (j = 0; j < gl_info->limits.buffers; ++j)
{
- if (entry->render_targets[j] == surface)
+ if (entry->d3d_render_targets[j] == surface)
{
callback(context, entry);
break;
@@ -835,21 +897,16 @@ void context_surface_update(struct wined3d_context *context, const struct wined3
if (!entry || context->rebind_fbo) return;
- for (i = 0; i < gl_info->limits.buffers; ++i)
+ for (i = 0; i < gl_info->limits.buffers + 1; ++i)
{
- if (surface == entry->render_targets[i])
+ if (surface->container->texture_rgb.name == entry->key.objects[i].object
+ || surface->container->texture_srgb.name == entry->key.objects[i].object)
{
- TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i);
+ TRACE("Updated surface %p is bound as attachment %u to the current FBO.\n", surface, i);
context->rebind_fbo = TRUE;
return;
}
}
-
- if (surface == entry->depth_stencil)
- {
- TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface);
- context->rebind_fbo = TRUE;
- }
}
static BOOL context_restore_pixel_format(struct wined3d_context *ctx)
@@ -1546,6 +1603,11 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
if (!ret->draw_buffers)
goto out;
+ ret->fbo_key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[gl_info->limits.buffers + 1]));
+ if (!ret->fbo_key)
+ goto out;
+
ret->free_timestamp_query_size = 4;
ret->free_timestamp_queries = HeapAlloc(GetProcessHeap(), 0,
ret->free_timestamp_query_size * sizeof(*ret->free_timestamp_queries));
@@ -1914,6 +1976,7 @@ out:
HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries);
+ HeapFree(GetProcessHeap(), 0, ret->fbo_key);
HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
HeapFree(GetProcessHeap(), 0, ret->blit_targets);
HeapFree(GetProcessHeap(), 0, ret);
@@ -1945,6 +2008,7 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont
device->shader_backend->shader_free_context_data(context);
device->adapter->fragment_pipe->free_context_data(context);
+ HeapFree(GetProcessHeap(), 0, context->fbo_key);
HeapFree(GetProcessHeap(), 0, context->draw_buffers);
HeapFree(GetProcessHeap(), 0, context->blit_targets);
device_context_remove(device, context);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8fd0d8b..e2c35c3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1311,6 +1311,7 @@ struct wined3d_context
GLuint fbo_read_binding;
GLuint fbo_draw_binding;
struct wined3d_surface **blit_targets;
+ struct wined3d_fbo_entry_key *fbo_key;
GLenum *draw_buffers;
DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */
@@ -2475,15 +2476,25 @@ struct wined3d_renderbuffer_entry
UINT height;
};
+struct wined3d_fbo_resource
+{
+ GLuint object;
+ GLuint level, target;
+};
+
struct fbo_entry
{
struct list entry;
- struct wined3d_surface **render_targets;
- struct wined3d_surface *depth_stencil;
- DWORD color_location, ds_location;
+ struct wined3d_surface **d3d_render_targets;
+ struct wined3d_surface *d3d_depth_stencil;
DWORD rt_mask;
BOOL attached;
GLuint id;
+ struct wined3d_fbo_entry_key
+ {
+ DWORD rb_namespace;
+ struct wined3d_fbo_resource objects[1];
+ } key;
};
struct wined3d_surface_ops
--
2.4.10
More information about the wine-patches
mailing list