[PATCH 4/6] wined3d: Create texture views for shader resource views.
Józef Kucia
jkucia at codeweavers.com
Mon Jun 6 04:39:05 CDT 2016
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
dlls/wined3d/context.c | 11 +--
dlls/wined3d/utils.c | 21 +++++
dlls/wined3d/view.c | 175 +++++++++++++++++++++++++++++++++++++++--
dlls/wined3d/wined3d_private.h | 9 +++
4 files changed, 201 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 845ca1d..e748f63 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -3292,7 +3292,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
struct wined3d_shader_sampler_map_entry *entry;
struct wined3d_shader_resource_view *view;
struct wined3d_sampler *sampler;
- struct wined3d_texture *texture;
struct wined3d_shader *shader;
unsigned int i, j, count;
GLuint sampler_name;
@@ -3332,12 +3331,6 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
continue;
}
- if (view->resource->type == WINED3D_RTYPE_BUFFER)
- {
- FIXME("Buffer shader resources not supported.\n");
- continue;
- }
-
if (entry->sampler_idx == WINED3D_SAMPLER_DEFAULT)
sampler_name = device->default_sampler;
else if ((sampler = state->sampler[shader_types[i].type][entry->sampler_idx]))
@@ -3345,12 +3338,10 @@ static void context_bind_shader_resources(struct wined3d_context *context, const
else
sampler_name = device->null_sampler;
- texture = texture_from_resource(view->resource);
context_active_texture(context, gl_info, shader_types[i].base_idx + entry->bind_idx);
- wined3d_texture_bind(texture, context, FALSE);
-
GL_EXTCALL(glBindSampler(shader_types[i].base_idx + entry->bind_idx, sampler_name));
checkGLcall("glBindSampler");
+ wined3d_shader_resource_view_bind(view, context);
}
}
}
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 97c3e19..4831ac3 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1661,6 +1661,7 @@ static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
format->block_width = typeless_format->block_width;
format->block_height = typeless_format->block_height;
format->block_byte_count = typeless_format->block_byte_count;
+ format->typeless_id = typeless_format->id;
for (j = 0; j < strlen(typed_formats[i].channels); ++j)
{
@@ -3731,6 +3732,26 @@ const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
}
}
+const char *debug_d3dviewtype(enum wined3d_view_type view_type)
+{
+ switch (view_type)
+ {
+#define WINED3D_TO_STR(x) case x: return #x
+ WINED3D_TO_STR(WINED3D_VTYPE_BUFFER);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_1D);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_1D_ARRAY);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_2D);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_2D_ARRAY);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_3D);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_CUBE);
+ WINED3D_TO_STR(WINED3D_VTYPE_TEXTURE_CUBE_ARRAY);
+#undef WINED3D_TO_STR
+ default:
+ FIXME("Unrecognized view type %#x.\n", view_type);
+ return "unrecognized";
+ }
+}
+
const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
{
switch (primitive_type)
diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c
index b12edec..46e2c26 100644
--- a/dlls/wined3d/view.c
+++ b/dlls/wined3d/view.c
@@ -24,6 +24,55 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+static BOOL gl_internal_format_equal(const struct wined3d_format *format1,
+ const struct wined3d_format *format2)
+{
+ return format1->id == format2->id
+ || (format1->glInternal == format2->glInternal
+ && format1->glGammaInternal == format2->glGammaInternal
+ && format1->rtInternal == format2->rtInternal);
+}
+
+static BOOL gl_texture_view_compatible(const struct wined3d_format *format1,
+ const struct wined3d_format *format2, enum wined3d_gl_resource_type gl_type)
+{
+ return gl_internal_format_equal(format1, format2)
+ || (format1->typeless_id == format2->typeless_id
+ && !(format1->flags[gl_type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
+ && !(format2->flags[gl_type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)));
+}
+
+static GLenum gl_texture_view_target(GLenum texture_target, enum wined3d_view_type view_type)
+{
+ static const struct
+ {
+ GLenum texture_target;
+ enum wined3d_view_type view_type;
+ GLenum view_target;
+ }
+ view_types[] =
+ {
+ {GL_TEXTURE_2D, WINED3D_VTYPE_TEXTURE_2D, GL_TEXTURE_2D},
+ {GL_TEXTURE_2D, WINED3D_VTYPE_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY},
+ {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_2D, GL_TEXTURE_2D},
+ {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY},
+ {GL_TEXTURE_2D_ARRAY, WINED3D_VTYPE_TEXTURE_CUBE, GL_TEXTURE_CUBE_MAP},
+ {GL_TEXTURE_3D, WINED3D_VTYPE_TEXTURE_3D, GL_TEXTURE_3D},
+ };
+
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(view_types); ++i)
+ {
+ if (view_types[i].texture_target == texture_target && view_types[i].view_type == view_type)
+ return view_types[i].view_target;
+ }
+
+ FIXME("Unhandled view type %s for texture target %#x.\n",
+ debug_d3dviewtype(view_type), texture_target);
+ return texture_target;
+}
+
ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *view)
{
ULONG refcount = InterlockedIncrement(&view->refcount);
@@ -185,6 +234,14 @@ ULONG CDECL wined3d_shader_resource_view_decref(struct wined3d_shader_resource_v
if (!refcount)
{
+ if (view->object)
+ {
+ struct wined3d_context *context = context_acquire(view->resource->device, NULL);
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ gl_info->gl_ops.gl.p_glDeleteTextures(1, &view->object);
+ checkGLcall("glDeleteTextures");
+ context_release(context);
+ }
/* Call wined3d_object_destroyed() before releasing the resource,
* since releasing the resource may end up destroying the parent. */
view->parent_ops->wined3d_object_destroyed(view->parent);
@@ -202,11 +259,97 @@ void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader
return view->parent;
}
+static void wined3d_shader_resource_view_create_texture_view(struct wined3d_shader_resource_view *view,
+ const struct wined3d_shader_resource_view_desc *desc, const struct wined3d_format *view_format,
+ struct wined3d_texture *texture)
+{
+ struct wined3d_context *context = context_acquire(texture->resource.device, NULL);
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ struct gl_texture *gl_texture;
+
+ if (!gl_info->supported[ARB_TEXTURE_VIEW])
+ {
+ context_release(context);
+ FIXME("OpenGL implementation does not support texture views.\n");
+ return;
+ }
+
+ view->target = gl_texture_view_target(texture->target, desc->view_type);
+
+ wined3d_texture_prepare_texture(texture, context, FALSE);
+ gl_texture = wined3d_texture_get_gl_texture(texture, FALSE);
+
+ gl_info->gl_ops.gl.p_glGenTextures(1, &view->object);
+ GL_EXTCALL(glTextureView(view->object, view->target, gl_texture->name, view_format->glInternal,
+ desc->u.texture.level_idx, desc->u.texture.level_count,
+ desc->u.texture.layer_idx, desc->u.texture.layer_count));
+ checkGLcall("Create texture view");
+
+ context_release(context);
+}
+
+static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
+ const struct wined3d_shader_resource_view_desc *desc, struct wined3d_resource *resource,
+ void *parent, const struct wined3d_parent_ops *parent_ops)
+{
+ const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
+ const struct wined3d_format *view_format;
+
+ view_format = wined3d_get_format(gl_info, desc->format_id);
+
+ view->refcount = 1;
+ view->parent = parent;
+ view->parent_ops = parent_ops;
+
+ view->target = GL_NONE;
+ view->object = 0;
+
+ if (resource->type == WINED3D_RTYPE_BUFFER)
+ {
+ FIXME("Buffer shader resource views not supported.\n");
+ }
+ else
+ {
+ struct wined3d_texture *texture = texture_from_resource(resource);
+
+ if (desc->u.texture.level_idx >= texture->level_count
+ || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
+ || desc->u.texture.layer_idx >= texture->layer_count
+ || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
+ return E_FAIL;
+
+ if (gl_internal_format_equal(resource->format, view_format)
+ && gl_texture_view_target(texture->target, desc->view_type) == texture->target
+ && !desc->u.texture.level_idx && desc->u.texture.level_count == texture->level_count
+ && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture->layer_count)
+ {
+ TRACE("Creating identity shader resource view.\n");
+ }
+ else if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1)
+ {
+ FIXME("Swapchain shader resource views not supported.\n");
+ }
+ else if (gl_texture_view_compatible(resource->format, view_format, resource->gl_type))
+ {
+ wined3d_shader_resource_view_create_texture_view(view, desc, view_format, texture);
+ }
+ else
+ {
+ FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
+ debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
+ }
+ }
+ wined3d_resource_incref(view->resource = resource);
+
+ return WINED3D_OK;
+}
+
HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_resource_view_desc *desc,
struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
struct wined3d_shader_resource_view **view)
{
struct wined3d_shader_resource_view *object;
+ HRESULT hr;
TRACE("desc %p, resource %p, parent %p, parent_ops %p, view %p.\n",
desc, resource, parent, parent_ops, view);
@@ -214,14 +357,36 @@ HRESULT CDECL wined3d_shader_resource_view_create(const struct wined3d_shader_re
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
- object->refcount = 1;
- object->resource = resource;
- wined3d_resource_incref(resource);
- object->parent = parent;
- object->parent_ops = parent_ops;
+ if (FAILED(hr = wined3d_shader_resource_view_init(object, desc, resource, parent, parent_ops)))
+ {
+ HeapFree(GetProcessHeap(), 0, object);
+ WARN("Failed to initialise view, hr %#x.\n", hr);
+ return hr;
+ }
TRACE("Created shader resource view %p.\n", object);
*view = object;
return WINED3D_OK;
}
+
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+ struct wined3d_context *context)
+{
+ struct wined3d_texture *texture;
+
+ if (view->object)
+ {
+ context_bind_texture(context, view->target, view->object);
+ return;
+ }
+
+ if (view->resource->type == WINED3D_RTYPE_BUFFER)
+ {
+ FIXME("Buffer shader resources not supported.\n");
+ return;
+ }
+
+ texture = wined3d_texture_from_resource(view->resource);
+ wined3d_texture_bind(texture, context, FALSE);
+}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f9a8ffa..4c7eaae 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3077,8 +3077,14 @@ struct wined3d_shader_resource_view
struct wined3d_resource *resource;
void *parent;
const struct wined3d_parent_ops *parent_ops;
+
+ GLenum target;
+ GLuint object;
};
+void wined3d_shader_resource_view_bind(struct wined3d_shader_resource_view *view,
+ struct wined3d_context *context) DECLSPEC_HIDDEN;
+
struct wined3d_swapchain_ops
{
void (*swapchain_present)(struct wined3d_swapchain *swapchain,
@@ -3148,6 +3154,7 @@ const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state) DECLSP
const char *debug_d3dtop(enum wined3d_texture_op d3dtop) DECLSPEC_HIDDEN;
const char *debug_d3dtstype(enum wined3d_transform_state tstype) DECLSPEC_HIDDEN;
const char *debug_d3dpool(enum wined3d_pool pool) DECLSPEC_HIDDEN;
+const char *debug_d3dviewtype(enum wined3d_view_type view_type) DECLSPEC_HIDDEN;
const char *debug_fboattachment(GLenum attachment) DECLSPEC_HIDDEN;
const char *debug_fbostatus(GLenum status) DECLSPEC_HIDDEN;
const char *debug_glerror(GLenum error) DECLSPEC_HIDDEN;
@@ -3532,6 +3539,8 @@ struct wined3d_format
struct color_fixup_desc color_fixup;
void (*convert)(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth);
+
+ enum wined3d_format_id typeless_id;
};
const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
--
2.7.3
More information about the wine-patches
mailing list