Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/wined3d/adapter_gl.c | 9 ++ dlls/wined3d/adapter_vk.c | 9 ++ dlls/wined3d/cs.c | 6 +- dlls/wined3d/utils.c | 3 + dlls/wined3d/view.c | 153 ++++++++++++++++++++++++++++++--- dlls/wined3d/wined3d_private.h | 6 +- 6 files changed, 172 insertions(+), 14 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 93f0e385e41..c3ce959a14f 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -5028,6 +5028,14 @@ static void adapter_gl_clear_uav(struct wined3d_context *context, clear_value, wined3d_context_gl(context)); }
+static void adapter_gl_generate_mipmap(struct wined3d_context *context, struct wined3d_shader_resource_view *view) +{ + TRACE("context %p, view %p.\n", context, view); + + wined3d_shader_resource_view_gl_generate_mipmap(wined3d_shader_resource_view_gl(view), + wined3d_context_gl(context)); +} + static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = { .adapter_destroy = adapter_gl_destroy, @@ -5062,6 +5070,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_gl_ops = .adapter_draw_primitive = draw_primitive, .adapter_dispatch_compute = dispatch_compute, .adapter_clear_uav = adapter_gl_clear_uav, + .adapter_generate_mipmap = adapter_gl_generate_mipmap, };
static void wined3d_adapter_gl_init_d3d_info(struct wined3d_adapter_gl *adapter_gl, uint32_t wined3d_creation_flags) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 7360ad33e40..973aebac9fa 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -1759,6 +1759,14 @@ static void adapter_vk_clear_uav(struct wined3d_context *context, clear_value, wined3d_context_vk(context)); }
+static void adapter_vk_generate_mipmap(struct wined3d_context *context, struct wined3d_shader_resource_view *view) +{ + TRACE("context %p, view %p.\n", context, view); + + wined3d_shader_resource_view_vk_generate_mipmap(wined3d_shader_resource_view_vk(view), + wined3d_context_vk(context)); +} + static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = { .adapter_destroy = adapter_vk_destroy, @@ -1793,6 +1801,7 @@ static const struct wined3d_adapter_ops wined3d_adapter_vk_ops = .adapter_draw_primitive = adapter_vk_draw_primitive, .adapter_dispatch_compute = adapter_vk_dispatch_compute, .adapter_clear_uav = adapter_vk_clear_uav, + .adapter_generate_mipmap = adapter_vk_generate_mipmap, };
static unsigned int wined3d_get_wine_vk_version(void) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 2aaeeab95a6..6bb628b5d13 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2596,8 +2596,12 @@ static void wined3d_cs_exec_generate_mipmaps(struct wined3d_cs *cs, const void * { const struct wined3d_cs_generate_mipmaps *op = data; struct wined3d_shader_resource_view *view = op->view; + struct wined3d_context *context; + + context = context_acquire(cs->c.device, NULL, 0); + cs->c.device->adapter->adapter_ops->adapter_generate_mipmap(context, view); + context_release(context);
- shader_resource_view_generate_mipmaps(view); wined3d_resource_release(view->resource); }
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 66caf8249f5..11284d19811 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4225,6 +4225,9 @@ static void init_vulkan_format_info(struct wined3d_format_vk *format, flags |= WINED3DFMT_FLAG_UNORDERED_ACCESS; }
+ if (!(~flags & (WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FILTERING))) + flags |= WINED3DFMT_FLAG_GEN_MIPMAP; + format->f.flags[WINED3D_GL_RES_TYPE_TEX_1D] |= flags; format->f.flags[WINED3D_GL_RES_TYPE_TEX_2D] |= flags; format->f.flags[WINED3D_GL_RES_TYPE_TEX_3D] |= flags; diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index 9650f6c08e3..74a100405aa 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -1194,23 +1194,18 @@ static void shader_resource_view_gl_bind_and_dirtify(struct wined3d_shader_resou wined3d_context_gl_bind_texture(context_gl, view_gl->gl_view.target, view_gl->gl_view.name); }
-void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) +void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *view_gl, + struct wined3d_context_gl *context_gl) { - struct wined3d_shader_resource_view_gl *view_gl = wined3d_shader_resource_view_gl(view); unsigned int i, j, layer_count, level_count, base_level, max_level; - const struct wined3d_gl_info *gl_info; + const struct wined3d_gl_info *gl_info = context_gl->gl_info; struct wined3d_texture_gl *texture_gl; - struct wined3d_context_gl *context_gl; - struct wined3d_context *context; struct gl_texture *gl_tex; DWORD location; BOOL srgb;
- TRACE("view %p.\n", view); + TRACE("view_gl %p.\n", view_gl);
- context = context_acquire(view_gl->v.resource->device, NULL, 0); - context_gl = wined3d_context_gl(context); - gl_info = context_gl->gl_info; layer_count = view_gl->v.desc.u.texture.layer_count; level_count = view_gl->v.desc.u.texture.level_count; base_level = view_gl->v.desc.u.texture.level_idx; @@ -1220,7 +1215,9 @@ void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view * srgb = !!(texture_gl->t.flags & WINED3D_TEXTURE_IS_SRGB); location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; for (i = 0; i < layer_count; ++i) - wined3d_texture_load_location(&texture_gl->t, i * level_count + base_level, context, location); + { + wined3d_texture_load_location(&texture_gl->t, i * level_count + base_level, &context_gl->c, location); + }
if (view_gl->gl_view.name) { @@ -1236,7 +1233,7 @@ void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view * if (gl_info->supported[ARB_SAMPLER_OBJECTS]) GL_EXTCALL(glBindSampler(context_gl->active_texture, 0)); gl_tex = wined3d_texture_gl_get_gl_texture(texture_gl, srgb); - if (context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + if (context_gl->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) { gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); @@ -1261,8 +1258,140 @@ void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view * gl_info->gl_ops.gl.p_glTexParameteri(texture_gl->target, GL_TEXTURE_MAX_LEVEL, texture_gl->t.level_count - 1); } +}
- context_release(context); +void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk, + struct wined3d_context_vk *context_vk) +{ + unsigned int i, j, layer_count, level_count, base_level, base_layer; + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkImageSubresourceRange vk_src_range, vk_dst_range; + struct wined3d_texture_vk *texture_vk; + VkCommandBuffer vk_command_buffer; + VkImageBlit region; + + TRACE("srv_vk %p.\n", srv_vk); + + layer_count = srv_vk->v.desc.u.texture.layer_count; + level_count = srv_vk->v.desc.u.texture.level_count; + base_level = srv_vk->v.desc.u.texture.level_idx; + base_layer = srv_vk->v.desc.u.texture.layer_idx; + + texture_vk = wined3d_texture_vk(texture_from_resource(srv_vk->v.resource)); + for (i = 0; i < layer_count; ++i) + { + if (!wined3d_texture_load_location(&texture_vk->t, + (base_layer + i) * level_count + base_level, &context_vk->c, WINED3D_LOCATION_TEXTURE_RGB)) + ERR("Failed to load source layer %u.\n", base_layer + i); + } + + if (context_vk->c.d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + FIXME("Unhandled sRGB read/write control.\n"); + + if (wined3d_format_vk(srv_vk->v.format)->vk_format != wined3d_format_vk(texture_vk->t.resource.format)->vk_format) + FIXME("Ignoring view format %s.\n", debug_d3dformat(srv_vk->v.format->id)); + + if (wined3d_resource_get_sample_count(&texture_vk->t.resource) > 1) + FIXME("Unhandled multi-sampled resource.\n"); + + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) + { + ERR("Failed to get command buffer.\n"); + return; + } + + vk_src_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format); + vk_src_range.baseMipLevel = base_level; + vk_src_range.levelCount = 1; + vk_src_range.baseArrayLayer = base_layer; + vk_src_range.layerCount = layer_count; + + vk_dst_range = vk_src_range; + ++vk_dst_range.baseMipLevel; + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags), + VK_ACCESS_TRANSFER_READ_BIT, + texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + texture_vk->vk_image, &vk_src_range); + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags), + VK_ACCESS_TRANSFER_WRITE_BIT, + texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + texture_vk->vk_image, &vk_dst_range); + + region.srcSubresource.aspectMask = vk_src_range.aspectMask; + region.srcSubresource.mipLevel = vk_src_range.baseMipLevel; + region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer; + region.srcSubresource.layerCount = vk_src_range.layerCount; + region.srcOffsets[0].x = 0; + region.srcOffsets[0].y = 0; + region.srcOffsets[0].z = 0; + + region.dstSubresource.aspectMask = vk_dst_range.aspectMask; + region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel; + region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer; + region.dstSubresource.layerCount = vk_dst_range.layerCount; + region.dstOffsets[0].x = 0; + region.dstOffsets[0].y = 0; + region.dstOffsets[0].z = 0; + + for (i = 1; i < level_count; ++i) + { + region.srcOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_src_range.baseMipLevel); + region.srcOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_src_range.baseMipLevel); + region.srcOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_src_range.baseMipLevel); + + region.dstOffsets[1].x = wined3d_texture_get_level_width(&texture_vk->t, vk_dst_range.baseMipLevel); + region.dstOffsets[1].y = wined3d_texture_get_level_height(&texture_vk->t, vk_dst_range.baseMipLevel); + region.dstOffsets[1].z = wined3d_texture_get_level_depth(&texture_vk->t, vk_dst_range.baseMipLevel); + + VK_CALL(vkCmdBlitImage(vk_command_buffer, texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, VK_FILTER_LINEAR)); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, texture_vk->layout, + texture_vk->vk_image, &vk_src_range); + + if (i == level_count - 1) + { + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture_vk->layout, + texture_vk->vk_image, &vk_dst_range); + } + else + { + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + texture_vk->vk_image, &vk_dst_range); + + region.srcSubresource.mipLevel = ++vk_src_range.baseMipLevel; + region.dstSubresource.mipLevel = ++vk_dst_range.baseMipLevel; + } + } + + for (i = 0; i < layer_count; ++i) + { + for (j = 1; j < level_count; ++j) + { + wined3d_texture_validate_location(&texture_vk->t, + (base_layer + i) * level_count + base_level + j, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_invalidate_location(&texture_vk->t, + (base_layer + i) * level_count + base_level + j, ~WINED3D_LOCATION_TEXTURE_RGB); + } + } + + wined3d_context_vk_reference_texture(context_vk, texture_vk); }
void CDECL wined3d_shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d4f1e4a9173..86d8061d005 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3344,6 +3344,7 @@ struct wined3d_adapter_ops const struct wined3d_dispatch_parameters *parameters); void (*adapter_clear_uav)(struct wined3d_context *context, struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value); + void (*adapter_generate_mipmap)(struct wined3d_context *context, struct wined3d_shader_resource_view *view); };
struct wined3d_output @@ -5051,7 +5052,6 @@ struct wined3d_shader_resource_view };
void wined3d_shader_resource_view_cleanup(struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN; -void shader_resource_view_generate_mipmaps(struct wined3d_shader_resource_view *view) DECLSPEC_HIDDEN;
struct wined3d_shader_resource_view_gl { @@ -5068,6 +5068,8 @@ static inline struct wined3d_shader_resource_view_gl *wined3d_shader_resource_vi
void wined3d_shader_resource_view_gl_bind(struct wined3d_shader_resource_view_gl *view_gl, unsigned int unit, struct wined3d_sampler_gl *sampler_gl, struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; +void wined3d_shader_resource_view_gl_generate_mipmap(struct wined3d_shader_resource_view_gl *srv_gl, + struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view_gl *view_gl, const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN; @@ -5103,6 +5105,8 @@ static inline void wined3d_shader_resource_view_vk_barrier(struct wined3d_shader wined3d_resource_vk_barrier(srv_vk->v.resource, context_vk, bind_mask); }
+void wined3d_shader_resource_view_vk_generate_mipmap(struct wined3d_shader_resource_view_vk *srv_vk, + struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; HRESULT wined3d_shader_resource_view_vk_init(struct wined3d_shader_resource_view_vk *view_vk, const struct wined3d_view_desc *desc, struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;