Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
Makefile.am | 5 +-
include/private/vkd3d_string.h | 57 ++++++++
include/private/vkd3d_utf8.h | 8 ++
libs/vkd3d-common/utf8.c | 248 +++++++++++++++++++++++++++++++++
libs/vkd3d/device.c | 1 +
libs/vkd3d/resource.c | 11 +-
libs/vkd3d/utils.c | 61 ++++++++
libs/vkd3d/vkd3d_private.h | 8 ++
libs/vkd3d/vulkan_procs.h | 2 +
9 files changed, 398 insertions(+), 3 deletions(-)
create mode 100644 include/private/vkd3d_string.h
create mode 100644 include/private/vkd3d_utf8.h
create mode 100644 libs/vkd3d-common/utf8.c
diff --git a/Makefile.am b/Makefile.am
index 7869b2e..abba599 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,7 +59,8 @@ noinst_LTLIBRARIES = libvkd3d-common.la
libvkd3d_common_la_SOURCES = \
include/private/vkd3d_debug.h \
libs/vkd3d-common/debug.c \
- libs/vkd3d-common/memory.c
+ libs/vkd3d-common/memory.c \
+ libs/vkd3d-common/utf8.c
lib_LTLIBRARIES = libvkd3d-shader.la libvkd3d.la libvkd3d-utils.la
@@ -88,6 +89,8 @@ libvkd3d_la_SOURCES = \
include/private/vkd3d_common.h \
include/private/vkd3d_debug.h \
include/private/vkd3d_memory.h \
+ include/private/vkd3d_string.h \
+ include/private/vkd3d_utf8.h \
include/private/vkd3d_test.h \
include/vkd3d_d3d12.idl \
include/vkd3d_d3dcommon.idl \
diff --git a/include/private/vkd3d_string.h b/include/private/vkd3d_string.h
new file mode 100644
index 0000000..07adc98
--- /dev/null
+++ b/include/private/vkd3d_string.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019 Zhiyi Zhang for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_STRING_H
+#define __VKD3D_STRING_H
+
+#include "vkd3d_memory.h"
+
+#include <inttypes.h>
+
+static inline size_t vkd3d_strlen_w16(const uint16_t *wstr)
+{
+ const uint16_t *s = wstr;
+ while (*s) s++;
+ return s - wstr;
+}
+
+static inline size_t vkd3d_strlen_w32(const uint32_t *wstr)
+{
+ const uint32_t *s = wstr;
+ while (*s) s++;
+ return s - wstr;
+}
+
+static inline WCHAR *vkd3d_strdup_w(const WCHAR *src, size_t wchar_size)
+{
+ size_t size;
+ WCHAR *dst;
+
+ if (wchar_size == 2)
+ size = (vkd3d_strlen_w16((const uint16_t *)src) + 1) * wchar_size;
+ else
+ size = (vkd3d_strlen_w32((const uint32_t *)src) + 1) * wchar_size;
+
+ if (!(dst = vkd3d_malloc(size)))
+ return NULL;
+
+ memcpy(dst, src, size);
+ return dst;
+}
+
+#endif /* __VKD3D_STRING_H */
\ No newline at end of file
diff --git a/include/private/vkd3d_utf8.h b/include/private/vkd3d_utf8.h
new file mode 100644
index 0000000..c7f1a07
--- /dev/null
+++ b/include/private/vkd3d_utf8.h
@@ -0,0 +1,8 @@
+#include "vkd3d_common.h"
+
+#include <inttypes.h>
+
+#define WC_ERR_INVALID_CHARS 0x0080
+
+int wine_utf8_wcstombs_w16(int flags, const uint16_t *src, int srclen, char *dst, int dstlen) DECLSPEC_HIDDEN;
+int wine_utf8_wcstombs_w32(int flags, const uint32_t *src, int srclen, char *dst, int dstlen) DECLSPEC_HIDDEN;
\ No newline at end of file
diff --git a/libs/vkd3d-common/utf8.c b/libs/vkd3d-common/utf8.c
new file mode 100644
index 0000000..da3e682
--- /dev/null
+++ b/libs/vkd3d-common/utf8.c
@@ -0,0 +1,248 @@
+/*
+ * UTF-8 support routines
+ *
+ * Copyright 2000 Alexandre Julliard
+ * Copyright 2019 Zhiyi Zhang for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_utf8.h"
+
+/* get the next char value taking surrogates into account */
+static inline unsigned int get_surrogate_value_w16( const uint16_t *src, unsigned int srclen )
+{
+ if (src[0] >= 0xd800 && src[0] <= 0xdfff) /* surrogate pair */
+ {
+ if (src[0] > 0xdbff || /* invalid high surrogate */
+ srclen <= 1 || /* missing low surrogate */
+ src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
+ return 0;
+ return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
+ }
+ return src[0];
+}
+
+/* query necessary dst length for src string */
+static inline int get_length_wcs_utf8_w16( int flags, const uint16_t *src, unsigned int srclen )
+{
+ int len;
+ unsigned int val;
+
+ for (len = 0; srclen; srclen--, src++)
+ {
+ if (*src < 0x80) /* 0x00-0x7f: 1 byte */
+ {
+ len++;
+ continue;
+ }
+ if (*src < 0x800) /* 0x80-0x7ff: 2 bytes */
+ {
+ len += 2;
+ continue;
+ }
+ if (!(val = get_surrogate_value_w16( src, srclen )))
+ {
+ if (flags & WC_ERR_INVALID_CHARS) return -2;
+ continue;
+ }
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ len += 3;
+ else /* 0x10000-0x10ffff: 4 bytes */
+ {
+ len += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return len;
+}
+
+/* wide char to UTF-8 string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+int wine_utf8_wcstombs_w16( int flags, const uint16_t *src, int srclen, char *dst, int dstlen )
+{
+ int len;
+
+ if (!dstlen) return get_length_wcs_utf8_w16( flags, src, srclen );
+
+ for (len = dstlen; srclen; srclen--, src++)
+ {
+ uint16_t ch = *src;
+ unsigned int val;
+
+ if (ch < 0x80) /* 0x00-0x7f: 1 byte */
+ {
+ if (!len--) return -1; /* overflow */
+ *dst++ = ch;
+ continue;
+ }
+
+ if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */
+ {
+ if ((len -= 2) < 0) return -1; /* overflow */
+ dst[1] = 0x80 | (ch & 0x3f);
+ ch >>= 6;
+ dst[0] = 0xc0 | ch;
+ dst += 2;
+ continue;
+ }
+
+ if (!(val = get_surrogate_value_w16( src, srclen )))
+ {
+ if (flags & WC_ERR_INVALID_CHARS) return -2;
+ continue;
+ }
+
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ {
+ if ((len -= 3) < 0) return -1; /* overflow */
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xe0 | val;
+ dst += 3;
+ }
+ else /* 0x10000-0x10ffff: 4 bytes */
+ {
+ if ((len -= 4) < 0) return -1; /* overflow */
+ dst[3] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xf0 | val;
+ dst += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return dstlen - len;
+}
+
+/* get the next char value taking surrogates into account */
+static inline unsigned int get_surrogate_value_w32( const uint32_t *src, unsigned int srclen )
+{
+ if (src[0] >= 0xd800 && src[0] <= 0xdfff) /* surrogate pair */
+ {
+ if (src[0] > 0xdbff || /* invalid high surrogate */
+ srclen <= 1 || /* missing low surrogate */
+ src[1] < 0xdc00 || src[1] > 0xdfff) /* invalid low surrogate */
+ return 0;
+ return 0x10000 + ((src[0] & 0x3ff) << 10) + (src[1] & 0x3ff);
+ }
+ return src[0];
+}
+
+/* query necessary dst length for src string */
+static inline int get_length_wcs_utf8_w32( int flags, const uint32_t *src, unsigned int srclen )
+{
+ int len;
+ unsigned int val;
+
+ for (len = 0; srclen; srclen--, src++)
+ {
+ if (*src < 0x80) /* 0x00-0x7f: 1 byte */
+ {
+ len++;
+ continue;
+ }
+ if (*src < 0x800) /* 0x80-0x7ff: 2 bytes */
+ {
+ len += 2;
+ continue;
+ }
+ if (!(val = get_surrogate_value_w32( src, srclen )))
+ {
+ if (flags & WC_ERR_INVALID_CHARS) return -2;
+ continue;
+ }
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ len += 3;
+ else /* 0x10000-0x10ffff: 4 bytes */
+ {
+ len += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return len;
+}
+
+/* wide char to UTF-8 string conversion */
+/* return -1 on dst buffer overflow, -2 on invalid input char */
+int wine_utf8_wcstombs_w32( int flags, const uint32_t *src, int srclen, char *dst, int dstlen )
+{
+ int len;
+
+ if (!dstlen) return get_length_wcs_utf8_w32( flags, src, srclen );
+
+ for (len = dstlen; srclen; srclen--, src++)
+ {
+ uint32_t ch = *src;
+ unsigned int val;
+
+ if (ch < 0x80) /* 0x00-0x7f: 1 byte */
+ {
+ if (!len--) return -1; /* overflow */
+ *dst++ = ch;
+ continue;
+ }
+
+ if (ch < 0x800) /* 0x80-0x7ff: 2 bytes */
+ {
+ if ((len -= 2) < 0) return -1; /* overflow */
+ dst[1] = 0x80 | (ch & 0x3f);
+ ch >>= 6;
+ dst[0] = 0xc0 | ch;
+ dst += 2;
+ continue;
+ }
+
+ if (!(val = get_surrogate_value_w32( src, srclen )))
+ {
+ if (flags & WC_ERR_INVALID_CHARS) return -2;
+ continue;
+ }
+
+ if (val < 0x10000) /* 0x800-0xffff: 3 bytes */
+ {
+ if ((len -= 3) < 0) return -1; /* overflow */
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xe0 | val;
+ dst += 3;
+ }
+ else /* 0x10000-0x10ffff: 4 bytes */
+ {
+ if ((len -= 4) < 0) return -1; /* overflow */
+ dst[3] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[2] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[1] = 0x80 | (val & 0x3f);
+ val >>= 6;
+ dst[0] = 0xf0 | val;
+ dst += 4;
+ src++;
+ srclen--;
+ }
+ }
+ return dstlen - len;
+}
\ No newline at end of file
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 64c8391..ff0c8c1 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -83,6 +83,7 @@ static const char * const required_device_extensions[] =
static const struct vkd3d_optional_extension_info optional_device_extensions[] =
{
+ {VK_EXT_DEBUG_MARKER_EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, EXT_debug_marker)},
{VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, KHR_push_descriptor)},
{VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME,
offsetof(struct vkd3d_vulkan_info, EXT_transform_feedback)},
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 6eba450..4ebfe30 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -2684,6 +2684,7 @@ static ULONG STDMETHODCALLTYPE d3d12_query_heap_Release(ID3D12QueryHeap *iface)
struct d3d12_device *device = heap->device;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ if (heap->name) vkd3d_free(heap->name);
vkd3d_private_store_destroy(&heap->private_store);
VK_CALL(vkDestroyQueryPool(device->vk_device, heap->vk_query_pool, NULL));
@@ -2729,10 +2730,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetPrivateDataInterface(ID3D12
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_SetName(ID3D12QueryHeap *iface, const WCHAR *name)
{
struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface);
+ HRESULT hr;
- FIXME("iface %p, name %s stub!\n", iface, debugstr_w(name, heap->device->wchar_size));
+ TRACE("iface %p, name %s.\n", iface, debugstr_w(name, heap->device->wchar_size));
- return E_NOTIMPL;
+ hr = vkd3d_set_vk_object_name(heap->device, (uint64_t)heap->vk_query_pool,
+ VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, name);
+ if (FAILED(hr)) return hr;
+
+ return vkd3d_set_name(&heap->name, name, heap->device->wchar_size);
}
static HRESULT STDMETHODCALLTYPE d3d12_query_heap_GetDevice(ID3D12QueryHeap *iface,
@@ -2784,6 +2790,7 @@ HRESULT d3d12_query_heap_create(struct d3d12_device *device, const D3D12_QUERY_H
object->ID3D12QueryHeap_iface.lpVtbl = &d3d12_query_heap_vtbl;
object->refcount = 1;
+ object->name = NULL;
object->device = device;
memset(object->availability_mask, 0, element_count * sizeof(*object->availability_mask));
diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c
index 0144fdc..10ed88f 100644
--- a/libs/vkd3d/utils.c
+++ b/libs/vkd3d/utils.c
@@ -642,3 +642,64 @@ HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store,
pthread_mutex_unlock(&store->mutex);
return hr;
}
+
+HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const WCHAR *name)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkDebugMarkerObjectNameInfoEXT info = {0};
+ char *buffer;
+ int length;
+ int size;
+ VkResult vr;
+
+ if (!name)
+ return E_INVALIDARG;
+
+ if (!device->vk_info.EXT_debug_marker)
+ return S_OK;
+
+ if (device->wchar_size == 2)
+ {
+ length = vkd3d_strlen_w16((const uint16_t *)name);
+ size = wine_utf8_wcstombs_w16(0, (const uint16_t *)name, length + 1, NULL, 0);
+ }
+ else
+ {
+ length = vkd3d_strlen_w32((const uint32_t *)name);
+ size = wine_utf8_wcstombs_w32(0, (const uint32_t *)name, length + 1, NULL, 0);
+ }
+
+ if (!(buffer = vkd3d_malloc(size)))
+ return E_OUTOFMEMORY;
+
+ if (device->wchar_size == 2)
+ wine_utf8_wcstombs_w16(0, (const uint16_t *)name, length + 1, buffer, size);
+ else
+ wine_utf8_wcstombs_w32(0, (const uint32_t *)name, length + 1, buffer, size);
+
+ info.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
+ info.objectType = vk_object_type;
+ info.object = vk_object;
+ info.pObjectName = buffer;
+ vr = VK_CALL(vkDebugMarkerSetObjectNameEXT(device->vk_device, &info));
+
+ vkd3d_free(buffer);
+ return vr == VK_SUCCESS ? S_OK : E_OUTOFMEMORY;
+}
+
+HRESULT vkd3d_set_name(WCHAR **dst, const WCHAR *src, size_t wchar_size)
+{
+ if (!src)
+ return E_INVALIDARG;
+
+ if (*dst)
+ vkd3d_free(*dst);
+
+ *dst = vkd3d_strdup_w(src, wchar_size);
+
+ if (!*dst)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
+}
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 73825bb..80e909d 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -25,6 +25,8 @@
#include "vkd3d_common.h"
#include "vkd3d_memory.h"
+#include "vkd3d_string.h"
+#include "vkd3d_utf8.h"
#include "list.h"
#include "rbtree.h"
@@ -86,6 +88,7 @@ struct vkd3d_vulkan_info
bool KHR_get_physical_device_properties2;
bool EXT_debug_report;
/* device extensions */
+ bool EXT_debug_marker;
bool KHR_push_descriptor;
bool EXT_transform_feedback;
bool EXT_vertex_attribute_divisor;
@@ -480,6 +483,7 @@ struct d3d12_query_heap
{
ID3D12QueryHeap ID3D12QueryHeap_iface;
LONG refcount;
+ WCHAR *name;
VkQueryPool vk_query_pool;
@@ -1026,4 +1030,8 @@ static inline void vkd3d_set_thread_name(const char *name)
#endif
}
+HRESULT vkd3d_set_vk_object_name(struct d3d12_device *device, uint64_t vk_object,
+ VkDebugReportObjectTypeEXT vk_object_type, const WCHAR *name) DECLSPEC_HIDDEN;
+HRESULT vkd3d_set_name(WCHAR **dst, const WCHAR *src, size_t wchar_size) DECLSPEC_HIDDEN;
+
#endif /* __VKD3D_PRIVATE_H */
diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h
index be983ec..b62af4e 100644
--- a/libs/vkd3d/vulkan_procs.h
+++ b/libs/vkd3d/vulkan_procs.h
@@ -174,6 +174,8 @@ VK_DEVICE_PFN(vkSetEvent)
VK_DEVICE_PFN(vkUnmapMemory)
VK_DEVICE_PFN(vkUpdateDescriptorSets)
VK_DEVICE_PFN(vkWaitForFences)
+/* VK_EXT_debug_marker */
+VK_DEVICE_EXT_PFN(vkDebugMarkerSetObjectNameEXT)
/* VK_KHR_push_descriptor */
VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR)
/* VK_EXT_transform_feedback */
--
2.19.2