Signed-off-by: Henri Verbeet <hverbeet(a)codeweavers.com>
---
dlls/wined3d/adapter_vk.c | 23 +++++--
dlls/wined3d/context_vk.c | 59 +++++++++++++++++
dlls/wined3d/sampler.c | 115 ++++++++++++++++++++++++++++++++-
dlls/wined3d/wined3d_private.h | 20 +++++-
4 files changed, 210 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index bd943a65afb..65850ab4ccc 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -1439,7 +1439,7 @@ static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_ac
static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
{
- struct wined3d_sampler *sampler_vk;
+ struct wined3d_sampler_vk *sampler_vk;
TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
device, desc, parent, parent_ops, sampler);
@@ -1450,16 +1450,31 @@ static HRESULT adapter_vk_create_sampler(struct wined3d_device *device, const st
wined3d_sampler_vk_init(sampler_vk, device, desc, parent, parent_ops);
TRACE("Created sampler %p.\n", sampler_vk);
- *sampler = sampler_vk;
+ *sampler = &sampler_vk->s;
return WINED3D_OK;
}
+static void wined3d_sampler_vk_destroy_object(void *object)
+{
+ struct wined3d_sampler_vk *sampler_vk = object;
+ struct wined3d_context_vk *context_vk;
+
+ context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
+
+ wined3d_context_vk_destroy_sampler(context_vk, sampler_vk->vk_image_info.sampler, sampler_vk->command_buffer_id);
+ heap_free(sampler_vk);
+
+ context_release(&context_vk->c);
+}
+
static void adapter_vk_destroy_sampler(struct wined3d_sampler *sampler)
{
- TRACE("sampler %p.\n", sampler);
+ struct wined3d_sampler_vk *sampler_vk = wined3d_sampler_vk(sampler);
+
+ TRACE("sampler_vk %p.\n", sampler_vk);
- wined3d_cs_destroy_object(sampler->device->cs, heap_free, sampler);
+ wined3d_cs_destroy_object(sampler->device->cs, wined3d_sampler_vk_destroy_object, sampler_vk);
}
static HRESULT adapter_vk_create_query(struct wined3d_device *device, enum wined3d_query_type type,
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 35b2b7eb7c7..20a0df181ca 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -29,6 +29,35 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op)
+{
+ switch (op)
+ {
+ case WINED3D_CMP_NEVER:
+ return VK_COMPARE_OP_NEVER;
+ case WINED3D_CMP_LESS:
+ return VK_COMPARE_OP_LESS;
+ case WINED3D_CMP_EQUAL:
+ return VK_COMPARE_OP_EQUAL;
+ case WINED3D_CMP_LESSEQUAL:
+ return VK_COMPARE_OP_LESS_OR_EQUAL;
+ case WINED3D_CMP_GREATER:
+ return VK_COMPARE_OP_GREATER;
+ case WINED3D_CMP_NOTEQUAL:
+ return VK_COMPARE_OP_NOT_EQUAL;
+ case WINED3D_CMP_GREATEREQUAL:
+ return VK_COMPARE_OP_GREATER_OR_EQUAL;
+ case WINED3D_CMP_ALWAYS:
+ return VK_COMPARE_OP_ALWAYS;
+ default:
+ if (!op)
+ WARN("Unhandled compare operation %#x.\n", op);
+ else
+ FIXME("Unhandled compare operation %#x.\n", op);
+ return VK_COMPARE_OP_NEVER;
+ }
+}
+
void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
struct wined3d_context_vk *context_vk)
{
@@ -519,6 +548,31 @@ void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk
o->command_buffer_id = command_buffer_id;
}
+void wined3d_context_vk_destroy_sampler(struct wined3d_context_vk *context_vk,
+ VkSampler vk_sampler, uint64_t command_buffer_id)
+{
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+ const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+ struct wined3d_retired_object_vk *o;
+
+ if (context_vk->completed_command_buffer_id > command_buffer_id)
+ {
+ VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
+ TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
+ return;
+ }
+
+ if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+ {
+ ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
+ return;
+ }
+
+ o->type = WINED3D_RETIRED_SAMPLER_VK;
+ o->u.vk_sampler = vk_sampler;
+ o->command_buffer_id = command_buffer_id;
+}
+
void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
{
size_t object_size, idx;
@@ -627,6 +681,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
break;
+ case WINED3D_RETIRED_SAMPLER_VK:
+ VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
+ TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
+ break;
+
default:
ERR("Unhandled object type %#x.\n", o->type);
break;
diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c
index c4f4d3eec30..8d909627a18 100644
--- a/dlls/wined3d/sampler.c
+++ b/dlls/wined3d/sampler.c
@@ -124,13 +124,124 @@ void wined3d_sampler_gl_init(struct wined3d_sampler_gl *sampler_gl, struct wined
wined3d_cs_init_object(device->cs, wined3d_sampler_gl_cs_init, sampler_gl);
}
-void wined3d_sampler_vk_init(struct wined3d_sampler *sampler_vk, struct wined3d_device *device,
+static VkFilter vk_filter_from_wined3d(enum wined3d_texture_filter_type f)
+{
+ switch (f)
+ {
+ default:
+ ERR("Invalid filter type %#x.\n", f);
+ case WINED3D_TEXF_POINT:
+ return VK_FILTER_NEAREST;
+ case WINED3D_TEXF_LINEAR:
+ return VK_FILTER_LINEAR;
+ }
+}
+
+static VkSamplerMipmapMode vk_mipmap_mode_from_wined3d(enum wined3d_texture_filter_type f)
+{
+ switch (f)
+ {
+ default:
+ ERR("Invalid filter type %#x.\n", f);
+ case WINED3D_TEXF_NONE:
+ case WINED3D_TEXF_POINT:
+ return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ case WINED3D_TEXF_LINEAR:
+ return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ }
+}
+
+static VkSamplerAddressMode vk_address_mode_from_wined3d(enum wined3d_texture_address a)
+{
+ switch (a)
+ {
+ default:
+ ERR("Invalid address mode %#x.\n", a);
+ case WINED3D_TADDRESS_WRAP:
+ return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ case WINED3D_TADDRESS_MIRROR:
+ return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+ case WINED3D_TADDRESS_CLAMP:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ case WINED3D_TADDRESS_BORDER:
+ return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ case WINED3D_TADDRESS_MIRROR_ONCE:
+ return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
+ }
+}
+
+static void wined3d_sampler_vk_cs_init(void *object)
+{
+ struct wined3d_sampler_vk *sampler_vk = object;
+ const struct wined3d_sampler_desc *desc;
+ const struct wined3d_d3d_info *d3d_info;
+ struct VkSamplerCreateInfo sampler_desc;
+ const struct wined3d_vk_info *vk_info;
+ struct wined3d_context_vk *context_vk;
+ struct wined3d_device_vk *device_vk;
+ VkSampler vk_sampler;
+ VkResult vr;
+
+ context_vk = wined3d_context_vk(context_acquire(sampler_vk->s.device, NULL, 0));
+ device_vk = wined3d_device_vk(context_vk->c.device);
+ d3d_info = context_vk->c.d3d_info;
+ vk_info = context_vk->vk_info;
+
+ desc = &sampler_vk->s.desc;
+ sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ sampler_desc.pNext = NULL;
+ sampler_desc.flags = 0;
+ sampler_desc.magFilter = vk_filter_from_wined3d(desc->mag_filter);
+ sampler_desc.minFilter = vk_filter_from_wined3d(desc->min_filter);
+ sampler_desc.mipmapMode = vk_mipmap_mode_from_wined3d(desc->mip_filter);
+ sampler_desc.addressModeU = vk_address_mode_from_wined3d(desc->address_u);
+ sampler_desc.addressModeV = vk_address_mode_from_wined3d(desc->address_v);
+ sampler_desc.addressModeW = vk_address_mode_from_wined3d(desc->address_w);
+ sampler_desc.mipLodBias = desc->lod_bias;
+ sampler_desc.anisotropyEnable = desc->max_anisotropy != 1;
+ sampler_desc.maxAnisotropy = desc->max_anisotropy;
+ sampler_desc.compareEnable = desc->compare;
+ sampler_desc.compareOp = vk_compare_op_from_wined3d(desc->comparison_func);
+ sampler_desc.minLod = desc->min_lod;
+ sampler_desc.maxLod = desc->max_lod;
+ sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
+ sampler_desc.unnormalizedCoordinates = VK_FALSE;
+
+ if ((desc->address_u == WINED3D_TADDRESS_BORDER || desc->address_v == WINED3D_TADDRESS_BORDER
+ || desc->address_w == WINED3D_TADDRESS_BORDER)
+ && (desc->border_color[0] != 0.0f || desc->border_color[1] != 0.0f
+ || desc->border_color[2] != 0.0f || desc->border_color[3] != 0.0f))
+ FIXME("Unhandled border colour {%.8e, %.8e, %.8e, %.8e}.\n",
+ desc->border_color[0], desc->border_color[1],
+ desc->border_color[2], desc->border_color[3]);
+ if (desc->mip_base_level)
+ FIXME("Unhandled mip_base_level %u.\n", desc->mip_base_level);
+ if ((d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) && !desc->srgb_decode)
+ FIXME("Unhandled srgb_decode %#x.\n", desc->srgb_decode);
+
+ vr = VK_CALL(vkCreateSampler(device_vk->vk_device, &sampler_desc, NULL, &vk_sampler));
+ context_release(&context_vk->c);
+ if (vr < 0)
+ {
+ ERR("Failed to create Vulkan sampler, vr %s.\n", wined3d_debug_vkresult(vr));
+ return;
+ }
+
+ TRACE("Created sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
+
+ sampler_vk->vk_image_info.sampler = vk_sampler;
+ sampler_vk->vk_image_info.imageView = VK_NULL_HANDLE;
+ sampler_vk->vk_image_info.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+}
+
+void wined3d_sampler_vk_init(struct wined3d_sampler_vk *sampler_vk, struct wined3d_device *device,
const struct wined3d_sampler_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{
TRACE("sampler_vk %p, device %p, desc %p, parent %p, parent_ops %p.\n",
sampler_vk, device, desc, parent, parent_ops);
- wined3d_sampler_init(sampler_vk, device, desc, parent, parent_ops);
+ wined3d_sampler_init(&sampler_vk->s, device, desc, parent, parent_ops);
+ wined3d_cs_init_object(device->cs, wined3d_sampler_vk_cs_init, sampler_vk);
}
HRESULT CDECL wined3d_sampler_create(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 2409728f270..7a412d7a8e7 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -300,6 +300,7 @@ extern const GLenum magLookup[WINED3D_TEXF_LINEAR + 1] DECLSPEC_HIDDEN;
GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f) DECLSPEC_HIDDEN;
VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN;
+VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op) DECLSPEC_HIDDEN;
VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags) DECLSPEC_HIDDEN;
static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func)
@@ -2232,6 +2233,7 @@ enum wined3d_retired_object_type_vk
WINED3D_RETIRED_IMAGE_VK,
WINED3D_RETIRED_BUFFER_VIEW_VK,
WINED3D_RETIRED_IMAGE_VIEW_VK,
+ WINED3D_RETIRED_SAMPLER_VK,
};
struct wined3d_retired_object_vk
@@ -2252,6 +2254,7 @@ struct wined3d_retired_object_vk
VkImage vk_image;
VkBufferView vk_buffer_view;
VkImageView vk_image_view;
+ VkSampler vk_sampler;
} u;
uint64_t command_buffer_id;
};
@@ -2334,6 +2337,8 @@ void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk
VkImageView vk_view, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
+void wined3d_context_vk_destroy_sampler(struct wined3d_context_vk *context_vk,
+ VkSampler vk_sampler, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
const struct wined3d_fb_state *fb, unsigned int rt_count,
@@ -4113,7 +4118,20 @@ void wined3d_sampler_gl_init(struct wined3d_sampler_gl *sampler_gl,
struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
-void wined3d_sampler_vk_init(struct wined3d_sampler *sampler_vk,
+struct wined3d_sampler_vk
+{
+ struct wined3d_sampler s;
+
+ VkDescriptorImageInfo vk_image_info;
+ uint64_t command_buffer_id;
+};
+
+static inline struct wined3d_sampler_vk *wined3d_sampler_vk(struct wined3d_sampler *sampler)
+{
+ return CONTAINING_RECORD(sampler, struct wined3d_sampler_vk, s);
+}
+
+void wined3d_sampler_vk_init(struct wined3d_sampler_vk *sampler_vk,
struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
void *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
--
2.20.1