Signed-off-by: Zhiyi Zhang zzhang@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 */