libs: Import upstream code from vkd3d release 1.3.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2022-03-03 09:47:58 +01:00
parent 9d82c27440
commit 97db56ab61
51 changed files with 62283 additions and 0 deletions

28
configure vendored
View File

@ -718,6 +718,8 @@ XSLT_PE_LIBS
XSLT_PE_CFLAGS
XML2_PE_LIBS
XML2_PE_CFLAGS
VKD3D_PE_LIBS
VKD3D_PE_CFLAGS
TIFF_PE_LIBS
TIFF_PE_CFLAGS
PNG_PE_LIBS
@ -1537,6 +1539,7 @@ enable_strmbase
enable_strmiids
enable_tiff
enable_uuid
enable_vkd3d
enable_wbemuuid
enable_wine
enable_wmcodecdspuuid
@ -1687,6 +1690,8 @@ PNG_PE_CFLAGS
PNG_PE_LIBS
TIFF_PE_CFLAGS
TIFF_PE_LIBS
VKD3D_PE_CFLAGS
VKD3D_PE_LIBS
XML2_PE_CFLAGS
XML2_PE_LIBS
XSLT_PE_CFLAGS
@ -2477,6 +2482,11 @@ Some influential environment variables:
C compiler flags for the PE tiff, overriding the bundled version
TIFF_PE_LIBS
Linker flags for the PE tiff, overriding the bundled version
VKD3D_PE_CFLAGS
C compiler flags for the PE vkd3d, overriding the bundled
version
VKD3D_PE_LIBS
Linker flags for the PE vkd3d, overriding the bundled version
XML2_PE_CFLAGS
C compiler flags for the PE xml2, overriding the bundled version
XML2_PE_LIBS
@ -13063,6 +13073,21 @@ fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: tiff cflags: $TIFF_PE_CFLAGS" >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: tiff libs: $TIFF_PE_LIBS" >&5
if ${VKD3D_PE_LIBS:+false} :
then :
VKD3D_PE_LIBS=vkd3d
if ${VKD3D_PE_CFLAGS:+false} :
then :
VKD3D_PE_CFLAGS="-I\$(top_srcdir)/libs/vkd3d/include"
else $as_nop
enable_vkd3d=no
fi
else $as_nop
enable_vkd3d=no
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: vkd3d cflags: $VKD3D_PE_CFLAGS" >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: vkd3d libs: $VKD3D_PE_LIBS" >&5
if ${XML2_PE_LIBS:+false} :
then :
XML2_PE_LIBS=xml2
@ -22036,6 +22061,7 @@ wine_fn_config_makefile libs/strmbase enable_strmbase
wine_fn_config_makefile libs/strmiids enable_strmiids
wine_fn_config_makefile libs/tiff enable_tiff
wine_fn_config_makefile libs/uuid enable_uuid
wine_fn_config_makefile libs/vkd3d enable_vkd3d
wine_fn_config_makefile libs/wbemuuid enable_wbemuuid
wine_fn_config_makefile libs/wine enable_wine
wine_fn_config_makefile libs/wmcodecdspuuid enable_wmcodecdspuuid
@ -23151,6 +23177,8 @@ PNG_PE_CFLAGS = $PNG_PE_CFLAGS
PNG_PE_LIBS = $PNG_PE_LIBS
TIFF_PE_CFLAGS = $TIFF_PE_CFLAGS
TIFF_PE_LIBS = $TIFF_PE_LIBS
VKD3D_PE_CFLAGS = $VKD3D_PE_CFLAGS
VKD3D_PE_LIBS = $VKD3D_PE_LIBS
XML2_PE_CFLAGS = $XML2_PE_CFLAGS
XML2_PE_LIBS = $XML2_PE_LIBS
XSLT_PE_CFLAGS = $XSLT_PE_CFLAGS

View File

@ -1104,6 +1104,7 @@ WINE_EXTLIB_FLAGS(LCMS2, lcms2, lcms2, "-I\$(top_srcdir)/libs/lcms2/include")
WINE_EXTLIB_FLAGS(MPG123, mpg123, mpg123, "-I\$(top_srcdir)/libs/mpg123/src/libmpg123")
WINE_EXTLIB_FLAGS(PNG, png, "png \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/png")
WINE_EXTLIB_FLAGS(TIFF, tiff, "tiff \$(ZLIB_PE_LIBS)", "-I\$(top_srcdir)/libs/tiff/libtiff")
WINE_EXTLIB_FLAGS(VKD3D, vkd3d, vkd3d, "-I\$(top_srcdir)/libs/vkd3d/include")
WINE_EXTLIB_FLAGS(XML2, xml2, xml2, "-I\$(top_srcdir)/libs/xml2/include -DLIBXML_STATIC")
WINE_EXTLIB_FLAGS(XSLT, xslt, xslt, "-I\$(top_srcdir)/libs/xslt -DLIBXSLT_STATIC")
WINE_EXTLIB_FLAGS(ZLIB, zlib, z, "-I\$(top_srcdir)/libs/zlib -DFAR= -DZ_SOLO")
@ -3245,6 +3246,7 @@ WINE_CONFIG_MAKEFILE(libs/strmbase)
WINE_CONFIG_MAKEFILE(libs/strmiids)
WINE_CONFIG_MAKEFILE(libs/tiff)
WINE_CONFIG_MAKEFILE(libs/uuid)
WINE_CONFIG_MAKEFILE(libs/vkd3d)
WINE_CONFIG_MAKEFILE(libs/wbemuuid)
WINE_CONFIG_MAKEFILE(libs/wine)
WINE_CONFIG_MAKEFILE(libs/wmcodecdspuuid)

26
libs/vkd3d/AUTHORS Normal file
View File

@ -0,0 +1,26 @@
Alexandre Julliard
Andrew Eikum
Andrey Gusev
Atharva Nimbalkar
Biswapriyo Nath
Chip Davis
Conor McCarthy
Derek Lesho
Francisco Casas
Giovanni Mascellani
Hans-Kristian Arntzen
Henri Verbeet
Isabella Bosia
Jactry Zeng
Joshua Ashton
Józef Kucia
Matteo Bruni
Nikolay Sivov
Philip Rebohle
Rémi Bernon
Robin Kertels
Stefan Dösinger
Sven Hesse
Vinson Lee
Zebediah Figura
Zhiyi Zhang

16
libs/vkd3d/COPYING Normal file
View File

@ -0,0 +1,16 @@
Copyright 2016-2022 the Vkd3d project authors (see the file AUTHORS for a
complete list)
Vkd3d 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 Street, Fifth Floor, Boston MA, 02110-1301 USA.

37
libs/vkd3d/Makefile.in Normal file
View File

@ -0,0 +1,37 @@
EXTLIB = libvkd3d.a
EXTRAINCL = -I$(srcdir)/include -I$(srcdir)/include/private -I$(srcdir)/libs/vkd3d -I$(srcdir)/libs/vkd3d-shader
EXTRADEFS = \
-DWINE_NO_NAMELESS_EXTENSION \
-DCONST_VTABLE \
-DLIBVKD3D_SOURCE \
-DLIBVKD3D_SHADER_SOURCE \
-DLIBVKD3D_UTILS_SOURCE
SOURCES = \
libs/vkd3d-common/blob.c \
libs/vkd3d-common/debug.c \
libs/vkd3d-common/error.c \
libs/vkd3d-common/memory.c \
libs/vkd3d-common/utf8.c \
libs/vkd3d-shader/checksum.c \
libs/vkd3d-shader/d3dbc.c \
libs/vkd3d-shader/dxbc.c \
libs/vkd3d-shader/glsl.c \
libs/vkd3d-shader/hlsl.c \
libs/vkd3d-shader/hlsl.l \
libs/vkd3d-shader/hlsl.y \
libs/vkd3d-shader/hlsl_codegen.c \
libs/vkd3d-shader/hlsl_constant_ops.c \
libs/vkd3d-shader/hlsl_sm1.c \
libs/vkd3d-shader/hlsl_sm4.c \
libs/vkd3d-shader/preproc.l \
libs/vkd3d-shader/preproc.y \
libs/vkd3d-shader/spirv.c \
libs/vkd3d-shader/trace.c \
libs/vkd3d-shader/vkd3d_shader_main.c \
libs/vkd3d/command.c \
libs/vkd3d/device.c \
libs/vkd3d/resource.c \
libs/vkd3d/state.c \
libs/vkd3d/utils.c \
libs/vkd3d/vkd3d_main.c

5
libs/vkd3d/config.h Normal file
View File

@ -0,0 +1,5 @@
#define PACKAGE_NAME "vkd3d"
#define PACKAGE_STRING "vkd3d 1.3"
#define PACKAGE_VERSION "1.3"
#define PATH_MAX 1024
#define SONAME_LIBVULKAN "vulkan-1.dll"

View File

@ -0,0 +1,27 @@
/*
* Copyright 2017 Józef Kucia 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_BLOB_H
#define __VKD3D_BLOB_H
#include "windows.h"
#include "d3dcommon.h"
HRESULT vkd3d_blob_create(void *buffer, SIZE_T size, ID3D10Blob **blob);
#endif /* __VKD3D_BLOB_H */

View File

@ -0,0 +1,245 @@
/*
* Copyright 2016 Józef Kucia 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_COMMON_H
#define __VKD3D_COMMON_H
#include "config.h"
#include "windows.h"
#include "vkd3d_types.h"
#include <ctype.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#endif
#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)
#define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])
#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)
#define VKD3D_MAKE_TAG(ch0, ch1, ch2, ch3) \
((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) \
| ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24))
static inline size_t align(size_t addr, size_t alignment)
{
return (addr + (alignment - 1)) & ~(alignment - 1);
}
#ifdef __GNUC__
# define VKD3D_NORETURN __attribute__((noreturn))
# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))
# define VKD3D_UNUSED __attribute__((unused))
#else
# define VKD3D_NORETURN
# define VKD3D_PRINTF_FUNC(fmt, args)
# define VKD3D_UNUSED
#endif /* __GNUC__ */
static inline unsigned int vkd3d_popcount(unsigned int v)
{
#ifdef _MSC_VER
return __popcnt(v);
#elif defined(__GNUC__) && (__GNUC__ >= 4)
return __builtin_popcount(v);
#else
v -= (v >> 1) & 0x55555555;
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
#endif
}
static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask)
{
unsigned int i, j;
for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i)
{
if (mask & (1u << i))
++j;
else if (j)
break;
}
return vkd3d_popcount(mask) == j;
}
/* Undefined for x == 0. */
static inline unsigned int vkd3d_log2i(unsigned int x)
{
#ifdef _WIN32
/* _BitScanReverse returns the index of the highest set bit,
* unlike clz which is 31 - index. */
ULONG result;
_BitScanReverse(&result, x);
return (unsigned int)result;
#elif defined(HAVE_BUILTIN_CLZ)
return __builtin_clz(x) ^ 0x1f;
#else
static const unsigned int l[] =
{
~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
};
unsigned int i;
return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24
: l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
#endif
}
static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
{
const char *str = haystack;
while (haystack_len >= needle_len)
{
if (!memcmp(str, needle, needle_len))
return (char *)str;
++str;
--haystack_len;
}
return NULL;
}
static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit)
{
#ifdef HAVE_BUILTIN_ADD_OVERFLOW
size_t sum;
return !__builtin_add_overflow(start, count, &sum) && sum <= limit;
#else
return start <= limit && count <= limit - start;
#endif
}
static inline uint16_t vkd3d_make_u16(uint8_t low, uint8_t high)
{
return low | ((uint16_t)high << 8);
}
static inline uint32_t vkd3d_make_u32(uint16_t low, uint16_t high)
{
return low | ((uint32_t)high << 16);
}
static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)
{
return (x > y) - (x < y);
}
static inline int ascii_isupper(int c)
{
return 'A' <= c && c <= 'Z';
}
static inline int ascii_tolower(int c)
{
return ascii_isupper(c) ? c - 'A' + 'a' : c;
}
static inline int ascii_strncasecmp(const char *a, const char *b, size_t n)
{
int c_a, c_b;
while (n--)
{
c_a = ascii_tolower(*a++);
c_b = ascii_tolower(*b++);
if (c_a != c_b || !c_a)
return c_a - c_b;
}
return 0;
}
static inline int ascii_strcasecmp(const char *a, const char *b)
{
int c_a, c_b;
do
{
c_a = ascii_tolower(*a++);
c_b = ascii_tolower(*b++);
} while (c_a == c_b && c_a != '\0');
return c_a - c_b;
}
#ifndef _WIN32
# if HAVE_SYNC_ADD_AND_FETCH
static inline LONG InterlockedIncrement(LONG volatile *x)
{
return __sync_add_and_fetch(x, 1);
}
static inline LONG InterlockedAdd(LONG volatile *x, LONG val)
{
return __sync_add_and_fetch(x, val);
}
# else
# error "InterlockedIncrement() not implemented for this platform"
# endif /* HAVE_SYNC_ADD_AND_FETCH */
# if HAVE_SYNC_SUB_AND_FETCH
static inline LONG InterlockedDecrement(LONG volatile *x)
{
return __sync_sub_and_fetch(x, 1);
}
# else
# error "InterlockedDecrement() not implemented for this platform"
# endif
#endif /* _WIN32 */
static inline void vkd3d_parse_version(const char *version, int *major, int *minor)
{
*major = atoi(version);
while (isdigit(*version))
++version;
if (*version == '.')
++version;
*minor = atoi(version);
}
HRESULT hresult_from_vkd3d_result(int vkd3d_result);
#endif /* __VKD3D_COMMON_H */

View File

@ -0,0 +1,118 @@
/*
* Copyright 2016 Józef Kucia 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_DEBUG_H
#define __VKD3D_DEBUG_H
#include "vkd3d_common.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef VKD3D_NO_TRACE_MESSAGES
#define TRACE(args...) do { } while (0)
#define TRACE_ON() (false)
#endif
#ifdef VKD3D_NO_DEBUG_MESSAGES
#define WARN(args...) do { } while (0)
#define FIXME(args...) do { } while (0)
#endif
enum vkd3d_dbg_level
{
VKD3D_DBG_LEVEL_NONE,
VKD3D_DBG_LEVEL_ERR,
VKD3D_DBG_LEVEL_FIXME,
VKD3D_DBG_LEVEL_WARN,
VKD3D_DBG_LEVEL_TRACE,
};
enum vkd3d_dbg_level vkd3d_dbg_get_level(void);
void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4);
const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2);
const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args);
const char *debugstr_a(const char *str);
const char *debugstr_an(const char *str, size_t n);
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size);
#define VKD3D_DBG_LOG(level) \
do { \
const enum vkd3d_dbg_level vkd3d_dbg_level = VKD3D_DBG_LEVEL_##level; \
VKD3D_DBG_PRINTF
#define VKD3D_DBG_LOG_ONCE(first_time_level, level) \
do { \
static bool vkd3d_dbg_next_time; \
const enum vkd3d_dbg_level vkd3d_dbg_level = vkd3d_dbg_next_time \
? VKD3D_DBG_LEVEL_##level : VKD3D_DBG_LEVEL_##first_time_level; \
vkd3d_dbg_next_time = true; \
VKD3D_DBG_PRINTF
#define VKD3D_DBG_PRINTF(...) \
vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)
#ifndef TRACE
#define TRACE VKD3D_DBG_LOG(TRACE)
#endif
#ifndef WARN
#define WARN VKD3D_DBG_LOG(WARN)
#endif
#ifndef FIXME
#define FIXME VKD3D_DBG_LOG(FIXME)
#endif
#define ERR VKD3D_DBG_LOG(ERR)
#ifndef TRACE_ON
#define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE)
#endif
#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)
#define VKD3D_DEBUG_ENV_NAME(name) const char *vkd3d_dbg_env_name = name
static inline const char *debugstr_guid(const GUID *guid)
{
if (!guid)
return "(null)";
return vkd3d_dbg_sprintf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
(unsigned long)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value);
struct vkd3d_debug_option
{
const char *name;
uint64_t flag;
};
bool vkd3d_debug_list_has_member(const char *string, const char *member);
uint64_t vkd3d_parse_debug_options(const char *string,
const struct vkd3d_debug_option *options, unsigned int option_count);
#endif /* __VKD3D_DEBUG_H */

View File

@ -0,0 +1,70 @@
/*
* Copyright 2016 Józef Kucia 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_MEMORY_H
#define __VKD3D_MEMORY_H
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "vkd3d_debug.h"
static inline void *vkd3d_malloc(size_t size)
{
void *ptr;
if (!(ptr = malloc(size)))
ERR("Out of memory.\n");
return ptr;
}
static inline void *vkd3d_realloc(void *ptr, size_t size)
{
if (!(ptr = realloc(ptr, size)))
ERR("Out of memory, size %zu.\n", size);
return ptr;
}
static inline void *vkd3d_calloc(size_t count, size_t size)
{
void *ptr;
assert(count <= ~(size_t)0 / size);
if (!(ptr = calloc(count, size)))
ERR("Out of memory.\n");
return ptr;
}
static inline void vkd3d_free(void *ptr)
{
free(ptr);
}
static inline char *vkd3d_strdup(const char *string)
{
size_t len = strlen(string) + 1;
char *ptr;
if ((ptr = vkd3d_malloc(len)))
memcpy(ptr, string, len);
return ptr;
}
bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size);
#endif /* __VKD3D_MEMORY_H */

View File

@ -0,0 +1,26 @@
/*
* 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_UTF8_H
#define __VKD3D_UTF8_H
#include "vkd3d_common.h"
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size);
#endif /* __VKD3D_UTF8_H */

View File

@ -0,0 +1 @@
#define VKD3D_VCS_ID " (git d773dc05c687)"

262
libs/vkd3d/include/vkd3d.h Normal file
View File

@ -0,0 +1,262 @@
/*
* Copyright 2016 Józef Kucia 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_H
#define __VKD3D_H
#include <vkd3d_types.h>
#ifndef VKD3D_NO_WIN32_TYPES
# include <windows.h>
# include <d3d12.h>
#endif /* VKD3D_NO_WIN32_TYPES */
#ifndef VKD3D_NO_VULKAN_H
# include <wine/vulkan.h>
#endif /* VKD3D_NO_VULKAN_H */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
enum vkd3d_structure_type
{
/* 1.0 */
VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO,
/* 1.1 */
VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO,
/* 1.2 */
VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
/* 1.3 */
VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
};
enum vkd3d_api_version
{
VKD3D_API_VERSION_1_0,
VKD3D_API_VERSION_1_1,
VKD3D_API_VERSION_1_2,
VKD3D_API_VERSION_1_3,
};
typedef HRESULT (*PFN_vkd3d_signal_event)(HANDLE event);
typedef void * (*PFN_vkd3d_thread)(void *data);
typedef void * (*PFN_vkd3d_create_thread)(PFN_vkd3d_thread thread_main, void *data);
typedef HRESULT (*PFN_vkd3d_join_thread)(void *thread);
struct vkd3d_instance;
struct vkd3d_instance_create_info
{
enum vkd3d_structure_type type;
const void *next;
PFN_vkd3d_signal_event pfn_signal_event;
PFN_vkd3d_create_thread pfn_create_thread;
PFN_vkd3d_join_thread pfn_join_thread;
size_t wchar_size;
/* If set to NULL, libvkd3d loads libvulkan. */
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr;
const char * const *instance_extensions;
uint32_t instance_extension_count;
};
/* Extends vkd3d_instance_create_info. Available since 1.1. */
struct vkd3d_optional_instance_extensions_info
{
enum vkd3d_structure_type type;
const void *next;
const char * const *extensions;
uint32_t extension_count;
};
/* Extends vkd3d_instance_create_info. Available since 1.2. */
struct vkd3d_application_info
{
enum vkd3d_structure_type type;
const void *next;
const char *application_name;
uint32_t application_version;
const char *engine_name; /* "vkd3d" if NULL */
uint32_t engine_version; /* vkd3d version if engine_name is NULL */
enum vkd3d_api_version api_version;
};
/* Extends vkd3d_instance_create_info. Available since 1.3. */
struct vkd3d_host_time_domain_info
{
enum vkd3d_structure_type type;
const void *next;
uint64_t ticks_per_second;
};
struct vkd3d_device_create_info
{
enum vkd3d_structure_type type;
const void *next;
D3D_FEATURE_LEVEL minimum_feature_level;
struct vkd3d_instance *instance;
const struct vkd3d_instance_create_info *instance_create_info;
VkPhysicalDevice vk_physical_device;
const char * const *device_extensions;
uint32_t device_extension_count;
IUnknown *parent;
LUID adapter_luid;
};
/* Extends vkd3d_device_create_info. Available since 1.2. */
struct vkd3d_optional_device_extensions_info
{
enum vkd3d_structure_type type;
const void *next;
const char * const *extensions;
uint32_t extension_count;
};
/* vkd3d_image_resource_create_info flags */
#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
struct vkd3d_image_resource_create_info
{
enum vkd3d_structure_type type;
const void *next;
VkImage vk_image;
D3D12_RESOURCE_DESC desc;
unsigned int flags;
D3D12_RESOURCE_STATES present_state;
};
#ifdef LIBVKD3D_SOURCE
# define VKD3D_API VKD3D_EXPORT
#else
# define VKD3D_API VKD3D_IMPORT
#endif
#ifndef VKD3D_NO_PROTOTYPES
VKD3D_API HRESULT vkd3d_create_instance(const struct vkd3d_instance_create_info *create_info,
struct vkd3d_instance **instance);
VKD3D_API ULONG vkd3d_instance_decref(struct vkd3d_instance *instance);
VKD3D_API VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance);
VKD3D_API ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
VKD3D_API HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
REFIID iid, void **device);
VKD3D_API IUnknown *vkd3d_get_device_parent(ID3D12Device *device);
VKD3D_API VkDevice vkd3d_get_vk_device(ID3D12Device *device);
VKD3D_API VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device);
VKD3D_API struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
VKD3D_API uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue);
VKD3D_API VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue);
VKD3D_API void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
VKD3D_API HRESULT vkd3d_create_image_resource(ID3D12Device *device,
const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
VKD3D_API ULONG vkd3d_resource_decref(ID3D12Resource *resource);
VKD3D_API ULONG vkd3d_resource_incref(ID3D12Resource *resource);
VKD3D_API HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
VKD3D_API HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
VKD3D_API VkFormat vkd3d_get_vk_format(DXGI_FORMAT format);
/* 1.1 */
VKD3D_API DXGI_FORMAT vkd3d_get_dxgi_format(VkFormat format);
/* 1.2 */
VKD3D_API HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob);
VKD3D_API HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
#endif /* VKD3D_NO_PROTOTYPES */
/*
* Function pointer typedefs for vkd3d functions.
*/
typedef HRESULT (*PFN_vkd3d_create_instance)(const struct vkd3d_instance_create_info *create_info,
struct vkd3d_instance **instance);
typedef ULONG (*PFN_vkd3d_instance_decref)(struct vkd3d_instance *instance);
typedef VkInstance (*PFN_vkd3d_instance_get_vk_instance)(struct vkd3d_instance *instance);
typedef ULONG (*PFN_vkd3d_instance_incref)(struct vkd3d_instance *instance);
typedef HRESULT (*PFN_vkd3d_create_device)(const struct vkd3d_device_create_info *create_info,
REFIID iid, void **device);
typedef IUnknown * (*PFN_vkd3d_get_device_parent)(ID3D12Device *device);
typedef VkDevice (*PFN_vkd3d_get_vk_device)(ID3D12Device *device);
typedef VkPhysicalDevice (*PFN_vkd3d_get_vk_physical_device)(ID3D12Device *device);
typedef struct vkd3d_instance * (*PFN_vkd3d_instance_from_device)(ID3D12Device *device);
typedef uint32_t (*PFN_vkd3d_get_vk_queue_family_index)(ID3D12CommandQueue *queue);
typedef VkQueue (*PFN_vkd3d_acquire_vk_queue)(ID3D12CommandQueue *queue);
typedef void (*PFN_vkd3d_release_vk_queue)(ID3D12CommandQueue *queue);
typedef HRESULT (*PFN_vkd3d_create_image_resource)(ID3D12Device *device,
const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource);
typedef ULONG (*PFN_vkd3d_resource_decref)(ID3D12Resource *resource);
typedef ULONG (*PFN_vkd3d_resource_incref)(ID3D12Resource *resource);
typedef HRESULT (*PFN_vkd3d_serialize_root_signature)(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
typedef HRESULT (*PFN_vkd3d_create_root_signature_deserializer)(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
typedef VkFormat (*PFN_vkd3d_get_vk_format)(DXGI_FORMAT format);
/* 1.1 */
typedef DXGI_FORMAT (*PFN_vkd3d_get_dxgi_format)(VkFormat format);
/* 1.2 */
typedef HRESULT (*PFN_vkd3d_serialize_versioned_root_signature)(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob);
typedef HRESULT (*PFN_vkd3d_create_versioned_root_signature_deserializer)(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __VKD3D_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/*
* Copyright 2016-2018 Józef Kucia 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_TYPES_H
#define __VKD3D_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \file vkd3d_types.h
*
* This file contains definitions for basic types used by vkd3d libraries.
*/
#define VKD3D_FORCE_32_BIT_ENUM(name) name##_FORCE_32BIT = 0x7fffffff
/**
* Result codes returned by some vkd3d functions. Error codes always have
* negative values; non-error codes never do.
*/
enum vkd3d_result
{
/** Success. */
VKD3D_OK = 0,
/** An unspecified failure occurred. */
VKD3D_ERROR = -1,
/** There are not enough resources available to complete the operation. */
VKD3D_ERROR_OUT_OF_MEMORY = -2,
/** One or more parameters passed to a vkd3d function were invalid. */
VKD3D_ERROR_INVALID_ARGUMENT = -3,
/** A shader passed to a vkd3d function was invalid. */
VKD3D_ERROR_INVALID_SHADER = -4,
/** The operation is not implemented in this version of vkd3d. */
VKD3D_ERROR_NOT_IMPLEMENTED = -5,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT),
};
#ifdef _WIN32
# define VKD3D_IMPORT
# define VKD3D_EXPORT
#elif defined(__GNUC__)
# define VKD3D_IMPORT
# define VKD3D_EXPORT __attribute__((visibility("default")))
#else
# define VKD3D_IMPORT
# define VKD3D_EXPORT
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __VKD3D_TYPES_H */

View File

@ -0,0 +1,131 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
#ifndef GLSLstd450_H
#define GLSLstd450_H
static const int GLSLstd450Version = 100;
static const int GLSLstd450Revision = 3;
enum GLSLstd450 {
GLSLstd450Bad = 0, // Don't use
GLSLstd450Round = 1,
GLSLstd450RoundEven = 2,
GLSLstd450Trunc = 3,
GLSLstd450FAbs = 4,
GLSLstd450SAbs = 5,
GLSLstd450FSign = 6,
GLSLstd450SSign = 7,
GLSLstd450Floor = 8,
GLSLstd450Ceil = 9,
GLSLstd450Fract = 10,
GLSLstd450Radians = 11,
GLSLstd450Degrees = 12,
GLSLstd450Sin = 13,
GLSLstd450Cos = 14,
GLSLstd450Tan = 15,
GLSLstd450Asin = 16,
GLSLstd450Acos = 17,
GLSLstd450Atan = 18,
GLSLstd450Sinh = 19,
GLSLstd450Cosh = 20,
GLSLstd450Tanh = 21,
GLSLstd450Asinh = 22,
GLSLstd450Acosh = 23,
GLSLstd450Atanh = 24,
GLSLstd450Atan2 = 25,
GLSLstd450Pow = 26,
GLSLstd450Exp = 27,
GLSLstd450Log = 28,
GLSLstd450Exp2 = 29,
GLSLstd450Log2 = 30,
GLSLstd450Sqrt = 31,
GLSLstd450InverseSqrt = 32,
GLSLstd450Determinant = 33,
GLSLstd450MatrixInverse = 34,
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
GLSLstd450ModfStruct = 36, // no OpVariable operand
GLSLstd450FMin = 37,
GLSLstd450UMin = 38,
GLSLstd450SMin = 39,
GLSLstd450FMax = 40,
GLSLstd450UMax = 41,
GLSLstd450SMax = 42,
GLSLstd450FClamp = 43,
GLSLstd450UClamp = 44,
GLSLstd450SClamp = 45,
GLSLstd450FMix = 46,
GLSLstd450IMix = 47, // Reserved
GLSLstd450Step = 48,
GLSLstd450SmoothStep = 49,
GLSLstd450Fma = 50,
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
GLSLstd450FrexpStruct = 52, // no OpVariable operand
GLSLstd450Ldexp = 53,
GLSLstd450PackSnorm4x8 = 54,
GLSLstd450PackUnorm4x8 = 55,
GLSLstd450PackSnorm2x16 = 56,
GLSLstd450PackUnorm2x16 = 57,
GLSLstd450PackHalf2x16 = 58,
GLSLstd450PackDouble2x32 = 59,
GLSLstd450UnpackSnorm2x16 = 60,
GLSLstd450UnpackUnorm2x16 = 61,
GLSLstd450UnpackHalf2x16 = 62,
GLSLstd450UnpackSnorm4x8 = 63,
GLSLstd450UnpackUnorm4x8 = 64,
GLSLstd450UnpackDouble2x32 = 65,
GLSLstd450Length = 66,
GLSLstd450Distance = 67,
GLSLstd450Cross = 68,
GLSLstd450Normalize = 69,
GLSLstd450FaceForward = 70,
GLSLstd450Reflect = 71,
GLSLstd450Refract = 72,
GLSLstd450FindILsb = 73,
GLSLstd450FindSMsb = 74,
GLSLstd450FindUMsb = 75,
GLSLstd450InterpolateAtCentroid = 76,
GLSLstd450InterpolateAtSample = 77,
GLSLstd450InterpolateAtOffset = 78,
GLSLstd450NMin = 79,
GLSLstd450NMax = 80,
GLSLstd450NClamp = 81,
GLSLstd450Count
};
#endif // #ifndef GLSLstd450_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
/*
* Copyright 2017 Józef Kucia 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
*/
#define COBJMACROS
#include "vkd3d.h"
#include "vkd3d_blob.h"
#include "vkd3d_debug.h"
#include "vkd3d_memory.h"
struct vkd3d_blob
{
ID3D10Blob ID3DBlob_iface;
LONG refcount;
void *buffer;
SIZE_T size;
};
static struct vkd3d_blob *impl_from_ID3DBlob(ID3DBlob *iface)
{
return CONTAINING_RECORD(iface, struct vkd3d_blob, ID3DBlob_iface);
}
static HRESULT STDMETHODCALLTYPE vkd3d_blob_QueryInterface(ID3DBlob *iface, REFIID riid, void **object)
{
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
if (IsEqualGUID(riid, &IID_ID3DBlob)
|| IsEqualGUID(riid, &IID_IUnknown))
{
ID3D10Blob_AddRef(iface);
*object = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
*object = NULL;
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE vkd3d_blob_AddRef(ID3DBlob *iface)
{
struct vkd3d_blob *blob = impl_from_ID3DBlob(iface);
ULONG refcount = InterlockedIncrement(&blob->refcount);
TRACE("%p increasing refcount to %u.\n", blob, refcount);
return refcount;
}
static ULONG STDMETHODCALLTYPE vkd3d_blob_Release(ID3DBlob *iface)
{
struct vkd3d_blob *blob = impl_from_ID3DBlob(iface);
ULONG refcount = InterlockedDecrement(&blob->refcount);
TRACE("%p decreasing refcount to %u.\n", blob, refcount);
if (!refcount)
{
vkd3d_free(blob->buffer);
vkd3d_free(blob);
}
return refcount;
}
static void * STDMETHODCALLTYPE vkd3d_blob_GetBufferPointer(ID3DBlob *iface)
{
struct vkd3d_blob *blob = impl_from_ID3DBlob(iface);
TRACE("iface %p.\n", iface);
return blob->buffer;
}
static SIZE_T STDMETHODCALLTYPE vkd3d_blob_GetBufferSize(ID3DBlob *iface)
{
struct vkd3d_blob *blob = impl_from_ID3DBlob(iface);
TRACE("iface %p.\n", iface);
return blob->size;
}
static const struct ID3D10BlobVtbl vkd3d_blob_vtbl =
{
/* IUnknown methods */
vkd3d_blob_QueryInterface,
vkd3d_blob_AddRef,
vkd3d_blob_Release,
/* ID3DBlob methods */
vkd3d_blob_GetBufferPointer,
vkd3d_blob_GetBufferSize
};
static void vkd3d_blob_init(struct vkd3d_blob *blob, void *buffer, SIZE_T size)
{
blob->ID3DBlob_iface.lpVtbl = &vkd3d_blob_vtbl;
blob->refcount = 1;
blob->buffer = buffer;
blob->size = size;
}
HRESULT vkd3d_blob_create(void *buffer, SIZE_T size, ID3D10Blob **blob)
{
struct vkd3d_blob *object;
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
vkd3d_blob_init(object, buffer, size);
TRACE("Created blob object %p.\n", object);
*blob = &object->ID3DBlob_iface;
return S_OK;
}

View File

@ -0,0 +1,347 @@
/*
* Copyright 2016 Józef Kucia 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_debug.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define VKD3D_DEBUG_BUFFER_COUNT 64
#define VKD3D_DEBUG_BUFFER_SIZE 512
extern const char *vkd3d_dbg_env_name;
static const char *debug_level_names[] =
{
/* VKD3D_DBG_LEVEL_NONE */ "none",
/* VKD3D_DBG_LEVEL_ERR */ "err",
/* VKD3D_DBG_LEVEL_FIXME */ "fixme",
/* VKD3D_DBG_LEVEL_WARN */ "warn",
/* VKD3D_DBG_LEVEL_TRACE */ "trace",
};
enum vkd3d_dbg_level vkd3d_dbg_get_level(void)
{
static unsigned int level = ~0u;
const char *vkd3d_debug;
unsigned int i;
if (level != ~0u)
return level;
if (!(vkd3d_debug = getenv(vkd3d_dbg_env_name)))
vkd3d_debug = "";
for (i = 0; i < ARRAY_SIZE(debug_level_names); ++i)
{
if (!strcmp(debug_level_names[i], vkd3d_debug))
{
level = i;
return level;
}
}
/* Default debug level. */
level = VKD3D_DBG_LEVEL_FIXME;
return level;
}
void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...)
{
va_list args;
if (vkd3d_dbg_get_level() < level)
return;
assert(level < ARRAY_SIZE(debug_level_names));
fprintf(stderr, "%s:%s: ", debug_level_names[level], function);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
static char *get_buffer(void)
{
static char buffers[VKD3D_DEBUG_BUFFER_COUNT][VKD3D_DEBUG_BUFFER_SIZE];
static LONG buffer_index;
LONG current_index;
current_index = InterlockedIncrement(&buffer_index) % ARRAY_SIZE(buffers);
return buffers[current_index];
}
const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args)
{
char *buffer;
buffer = get_buffer();
vsnprintf(buffer, VKD3D_DEBUG_BUFFER_SIZE, fmt, args);
buffer[VKD3D_DEBUG_BUFFER_SIZE - 1] = '\0';
return buffer;
}
const char *vkd3d_dbg_sprintf(const char *fmt, ...)
{
const char *buffer;
va_list args;
va_start(args, fmt);
buffer = vkd3d_dbg_vsprintf(fmt, args);
va_end(args);
return buffer;
}
static int get_escape_char(int c)
{
switch (c)
{
case '"':
case '\\':
return c;
case '\t':
return 't';
case '\n':
return 'n';
case '\r':
return 'r';
default:
return 0;
}
}
const char *debugstr_an(const char *str, size_t n)
{
char *buffer, *ptr;
int escape_char;
char c;
if (!str)
return "(null)";
if (n == SIZE_MAX)
n = strlen(str);
ptr = buffer = get_buffer();
*ptr++ = '"';
while (n-- && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 8)
{
c = *str++;
if ((escape_char = get_escape_char(c)))
{
*ptr++ = '\\';
*ptr++ = escape_char;
continue;
}
if (isprint(c))
{
*ptr++ = c;
}
else
{
*ptr++ = '\\';
sprintf(ptr, "%02x", c);
ptr += 2;
}
}
*ptr++ = '"';
if (++n)
{
*ptr++ = '.';
*ptr++ = '.';
*ptr++ = '.';
}
*ptr = '\0';
return buffer;
}
const char *debugstr_a(const char *str)
{
return debugstr_an(str, SIZE_MAX);
}
static const char *debugstr_w16(const uint16_t *wstr)
{
char *buffer, *ptr;
uint16_t c;
if (!wstr)
return "(null)";
ptr = buffer = get_buffer();
*ptr++ = '"';
while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
{
int escape_char = get_escape_char(c);
if (escape_char)
{
*ptr++ = '\\';
*ptr++ = escape_char;
continue;
}
if (isprint(c))
{
*ptr++ = c;
}
else
{
*ptr++ = '\\';
sprintf(ptr, "%04x", c);
ptr += 4;
}
}
*ptr++ = '"';
if (c)
{
*ptr++ = '.';
*ptr++ = '.';
*ptr++ = '.';
}
*ptr = '\0';
return buffer;
}
static const char *debugstr_w32(const uint32_t *wstr)
{
char *buffer, *ptr;
uint32_t c;
if (!wstr)
return "(null)";
ptr = buffer = get_buffer();
*ptr++ = '"';
while ((c = *wstr++) && ptr <= buffer + VKD3D_DEBUG_BUFFER_SIZE - 10)
{
int escape_char = get_escape_char(c);
if (escape_char)
{
*ptr++ = '\\';
*ptr++ = escape_char;
continue;
}
if (isprint(c))
{
*ptr++ = c;
}
else
{
*ptr++ = '\\';
sprintf(ptr, "%04x", c);
ptr += 4;
}
}
*ptr++ = '"';
if (c)
{
*ptr++ = '.';
*ptr++ = '.';
*ptr++ = '.';
}
*ptr = '\0';
return buffer;
}
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size)
{
if (wchar_size == 2)
return debugstr_w16((const uint16_t *)wstr);
return debugstr_w32((const uint32_t *)wstr);
}
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value)
{
const char *value = getenv(name);
unsigned long r;
char *end_ptr;
if (value)
{
errno = 0;
r = strtoul(value, &end_ptr, 0);
if (!errno && end_ptr != value)
return min(r, UINT_MAX);
}
return default_value;
}
static bool is_option_separator(char c)
{
return c == ',' || c == ';' || c == '\0';
}
bool vkd3d_debug_list_has_member(const char *string, const char *member)
{
char prev_char, next_char;
const char *p;
p = string;
while (p)
{
if ((p = strstr(p, member)))
{
prev_char = p > string ? p[-1] : 0;
p += strlen(member);
next_char = *p;
if (is_option_separator(prev_char) && is_option_separator(next_char))
return true;
}
}
return false;
}
uint64_t vkd3d_parse_debug_options(const char *string,
const struct vkd3d_debug_option *options, unsigned int option_count)
{
uint64_t flags = 0;
unsigned int i;
for (i = 0; i < option_count; ++i)
{
const struct vkd3d_debug_option *opt = &options[i];
if (vkd3d_debug_list_has_member(string, opt->name))
flags |= opt->flag;
}
return flags;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2018 Józef Kucia 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_common.h"
#include "vkd3d_debug.h"
HRESULT hresult_from_vkd3d_result(int vkd3d_result)
{
switch (vkd3d_result)
{
case VKD3D_OK:
return S_OK;
case VKD3D_ERROR_INVALID_SHADER:
WARN("Invalid shader bytecode.\n");
/* fall-through */
case VKD3D_ERROR:
return E_FAIL;
case VKD3D_ERROR_OUT_OF_MEMORY:
return E_OUTOFMEMORY;
case VKD3D_ERROR_INVALID_ARGUMENT:
return E_INVALIDARG;
case VKD3D_ERROR_NOT_IMPLEMENTED:
return E_NOTIMPL;
default:
FIXME("Unhandled vkd3d result %d.\n", vkd3d_result);
return E_FAIL;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2016 Henri Verbeet for CodeWeavers
* Copyright 2017 Józef Kucia 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_memory.h"
bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
{
size_t new_capacity, max_capacity;
void *new_elements;
if (element_count <= *capacity)
return true;
max_capacity = ~(size_t)0 / element_size;
if (max_capacity < element_count)
return false;
new_capacity = max(*capacity, 4);
while (new_capacity < element_count && new_capacity <= max_capacity / 2)
new_capacity *= 2;
if (new_capacity < element_count)
new_capacity = element_count;
if (!(new_elements = vkd3d_realloc(*elements, new_capacity * element_size)))
return false;
*elements = new_elements;
*capacity = new_capacity;
return true;
}

View File

@ -0,0 +1,164 @@
/*
* 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_memory.h"
#include "vkd3d_utf8.h"
#include <inttypes.h>
static size_t vkd3d_utf8_len(uint32_t c)
{
/* 0x00-0x7f: 1 byte */
if (c < 0x80)
return 1;
/* 0x80-0x7ff: 2 bytes */
if (c < 0x800)
return 2;
/* 0x800-0xffff: 3 bytes */
if (c < 0x10000)
return 3;
/* 0x10000-0x10ffff: 4 bytes */
return 4;
}
static void vkd3d_utf8_append(char **dst, uint32_t c)
{
char *d = *dst;
/* 0x00-0x7f: 1 byte */
if (c < 0x80)
{
d[0] = c;
*dst += 1;
return;
}
/* 0x80-0x7ff: 2 bytes */
if (c < 0x800)
{
d[1] = 0x80 | (c & 0x3f);
c >>= 6;
d[0] = 0xc0 | c;
*dst += 2;
return;
}
/* 0x800-0xffff: 3 bytes */
if (c < 0x10000) /* 0x800-0xffff: 3 bytes */
{
d[2] = 0x80 | (c & 0x3f);
c >>= 6;
d[1] = 0x80 | (c & 0x3f);
c >>= 6;
d[0] = 0xe0 | c;
*dst += 3;
return;
}
/* 0x10000-0x10ffff: 4 bytes */
d[3] = 0x80 | (c & 0x3f);
c >>= 6;
d[2] = 0x80 | (c & 0x3f);
c >>= 6;
d[1] = 0x80 | (c & 0x3f);
c >>= 6;
d[0] = 0xf0 | c;
*dst += 4;
}
static uint32_t vkd3d_utf16_read(const uint16_t **src)
{
const uint16_t *s = *src;
if (s[0] < 0xd800 || s[0] > 0xdfff) /* Not a surrogate pair. */
{
*src += 1;
return s[0];
}
if (s[0] > 0xdbff /* Invalid high surrogate. */
|| s[1] < 0xdc00 || s[1] > 0xdfff) /* Invalid low surrogate. */
{
*src += 1;
return 0;
}
*src += 2;
return 0x10000 + ((s[0] & 0x3ff) << 10) + (s[1] & 0x3ff);
}
static char *vkd3d_strdup_w16_utf8(const uint16_t *wstr)
{
const uint16_t *src = wstr;
size_t dst_size = 0;
char *dst, *utf8;
uint32_t c;
while (*src)
{
if (!(c = vkd3d_utf16_read(&src)))
continue;
dst_size += vkd3d_utf8_len(c);
}
++dst_size;
if (!(dst = vkd3d_malloc(dst_size)))
return NULL;
utf8 = dst;
src = wstr;
while (*src)
{
if (!(c = vkd3d_utf16_read(&src)))
continue;
vkd3d_utf8_append(&utf8, c);
}
*utf8 = 0;
return dst;
}
static char *vkd3d_strdup_w32_utf8(const uint32_t *wstr)
{
const uint32_t *src = wstr;
size_t dst_size = 0;
char *dst, *utf8;
while (*src)
dst_size += vkd3d_utf8_len(*src++);
++dst_size;
if (!(dst = vkd3d_malloc(dst_size)))
return NULL;
utf8 = dst;
src = wstr;
while (*src)
vkd3d_utf8_append(&utf8, *src++);
*utf8 = 0;
return dst;
}
char *vkd3d_strdup_w_utf8(const WCHAR *wstr, size_t wchar_size)
{
if (wchar_size == 2)
return vkd3d_strdup_w16_utf8((const uint16_t *)wstr);
return vkd3d_strdup_w32_utf8((const uint32_t *)wstr);
}

View File

@ -0,0 +1,300 @@
/*
* Copyright (C) 2001 Nikos Mavroyanopoulos
* Copyright (C) 2004 Hans Leidekker
*
* 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
*/
/*
* This code implements the MD5 message-digest algorithm.
* It is based on code in the public domain written by Colin
* Plumb in 1993. The algorithm is due to Ron Rivest.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* md5_ctx structure, pass it to md5_init, call md5_update as
* needed on buffers full of bytes, and then call md5_final, which
* will fill a supplied 16-byte array with the digest.
*/
#include "vkd3d_shader_private.h"
#define DXBC_CHECKSUM_BLOCK_SIZE 64
STATIC_ASSERT(sizeof(unsigned int) == 4);
struct md5_ctx
{
unsigned int i[2];
unsigned int buf[4];
unsigned char in[DXBC_CHECKSUM_BLOCK_SIZE];
unsigned char digest[16];
};
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. md5_update blocks
* the data and converts bytes into longwords for this routine.
*/
static void md5_transform(unsigned int buf[4], const unsigned int in[16])
{
unsigned int a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
* Note: this code is harmless on little-endian machines.
*/
static void byte_reverse(unsigned char *buf, unsigned longs)
{
unsigned int t;
do
{
t = vkd3d_make_u32(vkd3d_make_u16(buf[0], buf[1]), vkd3d_make_u16(buf[2], buf[3]));
*(unsigned int *)buf = t;
buf += 4;
} while (--longs);
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
static void md5_init(struct md5_ctx *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->i[0] = ctx->i[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
static void md5_update(struct md5_ctx *ctx, const unsigned char *buf, unsigned int len)
{
unsigned int t;
/* Update bitcount */
t = ctx->i[0];
if ((ctx->i[0] = t + (len << 3)) < t)
ctx->i[1]++; /* Carry from low to high */
ctx->i[1] += len >> 29;
t = (t >> 3) & 0x3f;
/* Handle any leading odd-sized chunks */
if (t)
{
unsigned char *p = (unsigned char *)ctx->in + t;
t = DXBC_CHECKSUM_BLOCK_SIZE - t;
if (len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byte_reverse(ctx->in, 16);
md5_transform(ctx->buf, (unsigned int *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= DXBC_CHECKSUM_BLOCK_SIZE)
{
memcpy(ctx->in, buf, DXBC_CHECKSUM_BLOCK_SIZE);
byte_reverse(ctx->in, 16);
md5_transform(ctx->buf, (unsigned int *)ctx->in);
buf += DXBC_CHECKSUM_BLOCK_SIZE;
len -= DXBC_CHECKSUM_BLOCK_SIZE;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
static void dxbc_checksum_final(struct md5_ctx *ctx)
{
unsigned int padding;
unsigned int length;
unsigned int count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->i[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
++count;
/* Bytes of padding needed to make 64 bytes */
padding = DXBC_CHECKSUM_BLOCK_SIZE - count;
/* Pad out to 56 mod 64 */
if (padding < 8)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, padding);
byte_reverse(ctx->in, 16);
md5_transform(ctx->buf, (unsigned int *)ctx->in);
/* Now fill the next block */
memset(ctx->in, 0, DXBC_CHECKSUM_BLOCK_SIZE);
}
else
{
/* Make place for bitcount at the beginning of the block */
memmove(&ctx->in[4], ctx->in, count);
/* Pad block to 60 bytes */
memset(p + 4, 0, padding - 4);
}
/* Append length in bits and transform */
length = ctx->i[0];
memcpy(&ctx->in[0], &length, sizeof(length));
byte_reverse(&ctx->in[4], 14);
length = ctx->i[0] >> 2 | 0x1;
memcpy(&ctx->in[DXBC_CHECKSUM_BLOCK_SIZE - 4], &length, sizeof(length));
md5_transform(ctx->buf, (unsigned int *)ctx->in);
byte_reverse((unsigned char *)ctx->buf, 4);
memcpy(ctx->digest, ctx->buf, 16);
}
#define DXBC_CHECKSUM_SKIP_BYTE_COUNT 20
void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4])
{
const uint8_t *ptr = dxbc;
struct md5_ctx ctx;
assert(size > DXBC_CHECKSUM_SKIP_BYTE_COUNT);
ptr += DXBC_CHECKSUM_SKIP_BYTE_COUNT;
size -= DXBC_CHECKSUM_SKIP_BYTE_COUNT;
md5_init(&ctx);
md5_update(&ctx, ptr, size);
dxbc_checksum_final(&ctx);
memcpy(checksum, ctx.digest, sizeof(ctx.digest));
}

View File

@ -0,0 +1,956 @@
/*
* Copyright 2002-2003 Jason Edmeades
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2006 Ivan Gyurdiev
* Copyright 2007-2008 Stefan Dösinger for CodeWeavers
* Copyright 2009, 2021 Henri Verbeet 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_shader_private.h"
#define VKD3D_SM1_VS 0xfffeu
#define VKD3D_SM1_PS 0xffffu
#define VKD3D_SM1_DCL_USAGE_SHIFT 0u
#define VKD3D_SM1_DCL_USAGE_MASK (0xfu << VKD3D_SM1_DCL_USAGE_SHIFT)
#define VKD3D_SM1_DCL_USAGE_INDEX_SHIFT 16u
#define VKD3D_SM1_DCL_USAGE_INDEX_MASK (0xfu << VKD3D_SM1_DCL_USAGE_INDEX_SHIFT)
#define VKD3D_SM1_RESOURCE_TYPE_SHIFT 27u
#define VKD3D_SM1_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM1_RESOURCE_TYPE_SHIFT)
#define VKD3D_SM1_OPCODE_MASK 0x0000ffffu
#define VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT 16u
#define VKD3D_SM1_INSTRUCTION_FLAGS_MASK (0xffu << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT)
#define VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT 24u
#define VKD3D_SM1_INSTRUCTION_LENGTH_MASK (0xfu << VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT)
#define VKD3D_SM1_COISSUE (0x1u << 30u)
#define VKD3D_SM1_COMMENT_SIZE_SHIFT 16u
#define VKD3D_SM1_COMMENT_SIZE_MASK (0x7fffu << VKD3D_SM1_COMMENT_SIZE_SHIFT)
#define VKD3D_SM1_INSTRUCTION_PREDICATED (0x1u << 28u)
#define VKD3D_SM1_INSTRUCTION_PARAMETER (0x1u << 31u)
#define VKD3D_SM1_REGISTER_NUMBER_MASK 0x000007ffu
#define VKD3D_SM1_REGISTER_TYPE_SHIFT 28u
#define VKD3D_SM1_REGISTER_TYPE_MASK (0x7u << VKD3D_SM1_REGISTER_TYPE_SHIFT)
#define VKD3D_SM1_REGISTER_TYPE_SHIFT2 8u
#define VKD3D_SM1_REGISTER_TYPE_MASK2 (0x18u << VKD3D_SM1_REGISTER_TYPE_SHIFT2)
#define VKD3D_SM1_ADDRESS_MODE_SHIFT 13u
#define VKD3D_SM1_ADDRESS_MODE_MASK (0x1u << VKD3D_SM1_ADDRESS_MODE_SHIFT)
#define VKD3D_SM1_DST_MODIFIER_SHIFT 20u
#define VKD3D_SM1_DST_MODIFIER_MASK (0xfu << VKD3D_SM1_DST_MODIFIER_SHIFT)
#define VKD3D_SM1_DSTSHIFT_SHIFT 24u
#define VKD3D_SM1_DSTSHIFT_MASK (0xfu << VKD3D_SM1_DSTSHIFT_SHIFT)
#define VKD3D_SM1_WRITEMASK_SHIFT 16u
#define VKD3D_SM1_WRITEMASK_MASK (0xfu << VKD3D_SM1_WRITEMASK_SHIFT)
#define VKD3D_SM1_SWIZZLE_SHIFT 16u
#define VKD3D_SM1_SWIZZLE_MASK (0xffu << VKD3D_SM1_SWIZZLE_SHIFT)
#define VKD3D_SM1_SWIZZLE_DEFAULT (0u | (1u << 2) | (2u << 4) | (3u << 6))
#define VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(idx) (2u * (idx))
#define VKD3D_SM1_SWIZZLE_COMPONENT_MASK(idx) (0x3u << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(idx))
#define VKD3D_SM1_SRC_MODIFIER_SHIFT 24u
#define VKD3D_SM1_SRC_MODIFIER_MASK (0xfu << VKD3D_SM1_SRC_MODIFIER_SHIFT)
#define VKD3D_SM1_END 0x0000ffffu
#define VKD3D_SM1_VERSION_MAJOR(version) (((version) >> 8u) & 0xffu)
#define VKD3D_SM1_VERSION_MINOR(version) (((version) >> 0u) & 0xffu)
enum vkd3d_sm1_address_mode_type
{
VKD3D_SM1_ADDRESS_MODE_ABSOLUTE = 0x0,
VKD3D_SM1_ADDRESS_MODE_RELATIVE = 0x1,
};
enum vkd3d_sm1_resource_type
{
VKD3D_SM1_RESOURCE_UNKNOWN = 0x0,
VKD3D_SM1_RESOURCE_TEXTURE_1D = 0x1,
VKD3D_SM1_RESOURCE_TEXTURE_2D = 0x2,
VKD3D_SM1_RESOURCE_TEXTURE_CUBE = 0x3,
VKD3D_SM1_RESOURCE_TEXTURE_3D = 0x4,
};
enum vkd3d_sm1_opcode
{
VKD3D_SM1_OP_NOP = 0x00,
VKD3D_SM1_OP_MOV = 0x01,
VKD3D_SM1_OP_ADD = 0x02,
VKD3D_SM1_OP_SUB = 0x03,
VKD3D_SM1_OP_MAD = 0x04,
VKD3D_SM1_OP_MUL = 0x05,
VKD3D_SM1_OP_RCP = 0x06,
VKD3D_SM1_OP_RSQ = 0x07,
VKD3D_SM1_OP_DP3 = 0x08,
VKD3D_SM1_OP_DP4 = 0x09,
VKD3D_SM1_OP_MIN = 0x0a,
VKD3D_SM1_OP_MAX = 0x0b,
VKD3D_SM1_OP_SLT = 0x0c,
VKD3D_SM1_OP_SGE = 0x0d,
VKD3D_SM1_OP_EXP = 0x0e,
VKD3D_SM1_OP_LOG = 0x0f,
VKD3D_SM1_OP_LIT = 0x10,
VKD3D_SM1_OP_DST = 0x11,
VKD3D_SM1_OP_LRP = 0x12,
VKD3D_SM1_OP_FRC = 0x13,
VKD3D_SM1_OP_M4x4 = 0x14,
VKD3D_SM1_OP_M4x3 = 0x15,
VKD3D_SM1_OP_M3x4 = 0x16,
VKD3D_SM1_OP_M3x3 = 0x17,
VKD3D_SM1_OP_M3x2 = 0x18,
VKD3D_SM1_OP_CALL = 0x19,
VKD3D_SM1_OP_CALLNZ = 0x1a,
VKD3D_SM1_OP_LOOP = 0x1b,
VKD3D_SM1_OP_RET = 0x1c,
VKD3D_SM1_OP_ENDLOOP = 0x1d,
VKD3D_SM1_OP_LABEL = 0x1e,
VKD3D_SM1_OP_DCL = 0x1f,
VKD3D_SM1_OP_POW = 0x20,
VKD3D_SM1_OP_CRS = 0x21,
VKD3D_SM1_OP_SGN = 0x22,
VKD3D_SM1_OP_ABS = 0x23,
VKD3D_SM1_OP_NRM = 0x24,
VKD3D_SM1_OP_SINCOS = 0x25,
VKD3D_SM1_OP_REP = 0x26,
VKD3D_SM1_OP_ENDREP = 0x27,
VKD3D_SM1_OP_IF = 0x28,
VKD3D_SM1_OP_IFC = 0x29,
VKD3D_SM1_OP_ELSE = 0x2a,
VKD3D_SM1_OP_ENDIF = 0x2b,
VKD3D_SM1_OP_BREAK = 0x2c,
VKD3D_SM1_OP_BREAKC = 0x2d,
VKD3D_SM1_OP_MOVA = 0x2e,
VKD3D_SM1_OP_DEFB = 0x2f,
VKD3D_SM1_OP_DEFI = 0x30,
VKD3D_SM1_OP_TEXCOORD = 0x40,
VKD3D_SM1_OP_TEXKILL = 0x41,
VKD3D_SM1_OP_TEX = 0x42,
VKD3D_SM1_OP_TEXBEM = 0x43,
VKD3D_SM1_OP_TEXBEML = 0x44,
VKD3D_SM1_OP_TEXREG2AR = 0x45,
VKD3D_SM1_OP_TEXREG2GB = 0x46,
VKD3D_SM1_OP_TEXM3x2PAD = 0x47,
VKD3D_SM1_OP_TEXM3x2TEX = 0x48,
VKD3D_SM1_OP_TEXM3x3PAD = 0x49,
VKD3D_SM1_OP_TEXM3x3TEX = 0x4a,
VKD3D_SM1_OP_TEXM3x3DIFF = 0x4b,
VKD3D_SM1_OP_TEXM3x3SPEC = 0x4c,
VKD3D_SM1_OP_TEXM3x3VSPEC = 0x4d,
VKD3D_SM1_OP_EXPP = 0x4e,
VKD3D_SM1_OP_LOGP = 0x4f,
VKD3D_SM1_OP_CND = 0x50,
VKD3D_SM1_OP_DEF = 0x51,
VKD3D_SM1_OP_TEXREG2RGB = 0x52,
VKD3D_SM1_OP_TEXDP3TEX = 0x53,
VKD3D_SM1_OP_TEXM3x2DEPTH = 0x54,
VKD3D_SM1_OP_TEXDP3 = 0x55,
VKD3D_SM1_OP_TEXM3x3 = 0x56,
VKD3D_SM1_OP_TEXDEPTH = 0x57,
VKD3D_SM1_OP_CMP = 0x58,
VKD3D_SM1_OP_BEM = 0x59,
VKD3D_SM1_OP_DP2ADD = 0x5a,
VKD3D_SM1_OP_DSX = 0x5b,
VKD3D_SM1_OP_DSY = 0x5c,
VKD3D_SM1_OP_TEXLDD = 0x5d,
VKD3D_SM1_OP_SETP = 0x5e,
VKD3D_SM1_OP_TEXLDL = 0x5f,
VKD3D_SM1_OP_BREAKP = 0x60,
VKD3D_SM1_OP_PHASE = 0xfffd,
VKD3D_SM1_OP_COMMENT = 0xfffe,
VKD3D_SM1_OP_END = 0Xffff,
};
struct vkd3d_sm1_opcode_info
{
enum vkd3d_sm1_opcode sm1_opcode;
unsigned int dst_count;
unsigned int src_count;
enum vkd3d_shader_opcode vkd3d_opcode;
struct
{
unsigned int major, minor;
} min_version, max_version;
};
struct vkd3d_shader_sm1_parser
{
const struct vkd3d_sm1_opcode_info *opcode_table;
const uint32_t *start, *end;
bool abort;
struct vkd3d_shader_src_param src_rel_addr[4];
struct vkd3d_shader_src_param pred_rel_addr;
struct vkd3d_shader_src_param dst_rel_addr;
struct vkd3d_shader_src_param src_param[4];
struct vkd3d_shader_src_param pred_param;
struct vkd3d_shader_dst_param dst_param;
struct vkd3d_shader_parser p;
};
/* This table is not order or position dependent. */
static const struct vkd3d_sm1_opcode_info vs_opcode_table[] =
{
/* Arithmetic */
{VKD3D_SM1_OP_NOP, 0, 0, VKD3DSIH_NOP},
{VKD3D_SM1_OP_MOV, 1, 1, VKD3DSIH_MOV},
{VKD3D_SM1_OP_MOVA, 1, 1, VKD3DSIH_MOVA, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_ADD, 1, 2, VKD3DSIH_ADD},
{VKD3D_SM1_OP_SUB, 1, 2, VKD3DSIH_SUB},
{VKD3D_SM1_OP_MAD, 1, 3, VKD3DSIH_MAD},
{VKD3D_SM1_OP_MUL, 1, 2, VKD3DSIH_MUL},
{VKD3D_SM1_OP_RCP, 1, 1, VKD3DSIH_RCP},
{VKD3D_SM1_OP_RSQ, 1, 1, VKD3DSIH_RSQ},
{VKD3D_SM1_OP_DP3, 1, 2, VKD3DSIH_DP3},
{VKD3D_SM1_OP_DP4, 1, 2, VKD3DSIH_DP4},
{VKD3D_SM1_OP_MIN, 1, 2, VKD3DSIH_MIN},
{VKD3D_SM1_OP_MAX, 1, 2, VKD3DSIH_MAX},
{VKD3D_SM1_OP_SLT, 1, 2, VKD3DSIH_SLT},
{VKD3D_SM1_OP_SGE, 1, 2, VKD3DSIH_SGE},
{VKD3D_SM1_OP_ABS, 1, 1, VKD3DSIH_ABS},
{VKD3D_SM1_OP_EXP, 1, 1, VKD3DSIH_EXP},
{VKD3D_SM1_OP_LOG, 1, 1, VKD3DSIH_LOG},
{VKD3D_SM1_OP_EXPP, 1, 1, VKD3DSIH_EXPP},
{VKD3D_SM1_OP_LOGP, 1, 1, VKD3DSIH_LOGP},
{VKD3D_SM1_OP_LIT, 1, 1, VKD3DSIH_LIT},
{VKD3D_SM1_OP_DST, 1, 2, VKD3DSIH_DST},
{VKD3D_SM1_OP_LRP, 1, 3, VKD3DSIH_LRP},
{VKD3D_SM1_OP_FRC, 1, 1, VKD3DSIH_FRC},
{VKD3D_SM1_OP_POW, 1, 2, VKD3DSIH_POW},
{VKD3D_SM1_OP_CRS, 1, 2, VKD3DSIH_CRS},
{VKD3D_SM1_OP_SGN, 1, 3, VKD3DSIH_SGN, {2, 0}, { 2, 1}},
{VKD3D_SM1_OP_SGN, 1, 1, VKD3DSIH_SGN, {3, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_NRM, 1, 1, VKD3DSIH_NRM,},
{VKD3D_SM1_OP_SINCOS, 1, 3, VKD3DSIH_SINCOS, {2, 0}, { 2, 1}},
{VKD3D_SM1_OP_SINCOS, 1, 1, VKD3DSIH_SINCOS, {3, 0}, {~0u, ~0u}},
/* Matrix */
{VKD3D_SM1_OP_M4x4, 1, 2, VKD3DSIH_M4x4},
{VKD3D_SM1_OP_M4x3, 1, 2, VKD3DSIH_M4x3},
{VKD3D_SM1_OP_M3x4, 1, 2, VKD3DSIH_M3x4},
{VKD3D_SM1_OP_M3x3, 1, 2, VKD3DSIH_M3x3},
{VKD3D_SM1_OP_M3x2, 1, 2, VKD3DSIH_M3x2},
/* Declarations */
{VKD3D_SM1_OP_DCL, 0, 2, VKD3DSIH_DCL},
/* Constant definitions */
{VKD3D_SM1_OP_DEF, 1, 4, VKD3DSIH_DEF},
{VKD3D_SM1_OP_DEFB, 1, 1, VKD3DSIH_DEFB},
{VKD3D_SM1_OP_DEFI, 1, 4, VKD3DSIH_DEFI},
/* Control flow */
{VKD3D_SM1_OP_REP, 0, 1, VKD3DSIH_REP, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDREP, 0, 0, VKD3DSIH_ENDREP, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_IF, 0, 1, VKD3DSIH_IF, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_IFC, 0, 2, VKD3DSIH_IFC, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_ELSE, 0, 0, VKD3DSIH_ELSE, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDIF, 0, 0, VKD3DSIH_ENDIF, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAK, 0, 0, VKD3DSIH_BREAK, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAKC, 0, 2, VKD3DSIH_BREAKC, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAKP, 0, 1, VKD3DSIH_BREAKP},
{VKD3D_SM1_OP_CALL, 0, 1, VKD3DSIH_CALL, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_CALLNZ, 0, 2, VKD3DSIH_CALLNZ, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_LOOP, 0, 2, VKD3DSIH_LOOP, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_RET, 0, 0, VKD3DSIH_RET, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDLOOP, 0, 0, VKD3DSIH_ENDLOOP, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_LABEL, 0, 1, VKD3DSIH_LABEL, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_SETP, 1, 2, VKD3DSIH_SETP},
{VKD3D_SM1_OP_TEXLDL, 1, 2, VKD3DSIH_TEXLDL, {3, 0}, {~0u, ~0u}},
{0, 0, 0, VKD3DSIH_INVALID},
};
static const struct vkd3d_sm1_opcode_info ps_opcode_table[] =
{
/* Arithmetic */
{VKD3D_SM1_OP_NOP, 0, 0, VKD3DSIH_NOP},
{VKD3D_SM1_OP_MOV, 1, 1, VKD3DSIH_MOV},
{VKD3D_SM1_OP_ADD, 1, 2, VKD3DSIH_ADD},
{VKD3D_SM1_OP_SUB, 1, 2, VKD3DSIH_SUB},
{VKD3D_SM1_OP_MAD, 1, 3, VKD3DSIH_MAD},
{VKD3D_SM1_OP_MUL, 1, 2, VKD3DSIH_MUL},
{VKD3D_SM1_OP_RCP, 1, 1, VKD3DSIH_RCP},
{VKD3D_SM1_OP_RSQ, 1, 1, VKD3DSIH_RSQ},
{VKD3D_SM1_OP_DP3, 1, 2, VKD3DSIH_DP3},
{VKD3D_SM1_OP_DP4, 1, 2, VKD3DSIH_DP4},
{VKD3D_SM1_OP_MIN, 1, 2, VKD3DSIH_MIN},
{VKD3D_SM1_OP_MAX, 1, 2, VKD3DSIH_MAX},
{VKD3D_SM1_OP_SLT, 1, 2, VKD3DSIH_SLT},
{VKD3D_SM1_OP_SGE, 1, 2, VKD3DSIH_SGE},
{VKD3D_SM1_OP_ABS, 1, 1, VKD3DSIH_ABS},
{VKD3D_SM1_OP_EXP, 1, 1, VKD3DSIH_EXP},
{VKD3D_SM1_OP_LOG, 1, 1, VKD3DSIH_LOG},
{VKD3D_SM1_OP_EXPP, 1, 1, VKD3DSIH_EXPP},
{VKD3D_SM1_OP_LOGP, 1, 1, VKD3DSIH_LOGP},
{VKD3D_SM1_OP_DST, 1, 2, VKD3DSIH_DST},
{VKD3D_SM1_OP_LRP, 1, 3, VKD3DSIH_LRP},
{VKD3D_SM1_OP_FRC, 1, 1, VKD3DSIH_FRC},
{VKD3D_SM1_OP_CND, 1, 3, VKD3DSIH_CND, {1, 0}, { 1, 4}},
{VKD3D_SM1_OP_CMP, 1, 3, VKD3DSIH_CMP, {1, 2}, { 3, 0}},
{VKD3D_SM1_OP_POW, 1, 2, VKD3DSIH_POW},
{VKD3D_SM1_OP_CRS, 1, 2, VKD3DSIH_CRS},
{VKD3D_SM1_OP_NRM, 1, 1, VKD3DSIH_NRM},
{VKD3D_SM1_OP_SINCOS, 1, 3, VKD3DSIH_SINCOS, {2, 0}, { 2, 1}},
{VKD3D_SM1_OP_SINCOS, 1, 1, VKD3DSIH_SINCOS, {3, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_DP2ADD, 1, 3, VKD3DSIH_DP2ADD, {2, 0}, {~0u, ~0u}},
/* Matrix */
{VKD3D_SM1_OP_M4x4, 1, 2, VKD3DSIH_M4x4},
{VKD3D_SM1_OP_M4x3, 1, 2, VKD3DSIH_M4x3},
{VKD3D_SM1_OP_M3x4, 1, 2, VKD3DSIH_M3x4},
{VKD3D_SM1_OP_M3x3, 1, 2, VKD3DSIH_M3x3},
{VKD3D_SM1_OP_M3x2, 1, 2, VKD3DSIH_M3x2},
/* Declarations */
{VKD3D_SM1_OP_DCL, 0, 2, VKD3DSIH_DCL},
/* Constant definitions */
{VKD3D_SM1_OP_DEF, 1, 4, VKD3DSIH_DEF},
{VKD3D_SM1_OP_DEFB, 1, 1, VKD3DSIH_DEFB},
{VKD3D_SM1_OP_DEFI, 1, 4, VKD3DSIH_DEFI},
/* Control flow */
{VKD3D_SM1_OP_REP, 0, 1, VKD3DSIH_REP, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDREP, 0, 0, VKD3DSIH_ENDREP, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_IF, 0, 1, VKD3DSIH_IF, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_IFC, 0, 2, VKD3DSIH_IFC, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_ELSE, 0, 0, VKD3DSIH_ELSE, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDIF, 0, 0, VKD3DSIH_ENDIF, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAK, 0, 0, VKD3DSIH_BREAK, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAKC, 0, 2, VKD3DSIH_BREAKC, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_BREAKP, 0, 1, VKD3DSIH_BREAKP},
{VKD3D_SM1_OP_CALL, 0, 1, VKD3DSIH_CALL, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_CALLNZ, 0, 2, VKD3DSIH_CALLNZ, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_LOOP, 0, 2, VKD3DSIH_LOOP, {3, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_RET, 0, 0, VKD3DSIH_RET, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_ENDLOOP, 0, 0, VKD3DSIH_ENDLOOP, {3, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_LABEL, 0, 1, VKD3DSIH_LABEL, {2, 1}, {~0u, ~0u}},
/* Texture */
{VKD3D_SM1_OP_TEXCOORD, 1, 0, VKD3DSIH_TEXCOORD, {0, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCOORD, {1 ,4}, { 1, 4}},
{VKD3D_SM1_OP_TEXKILL, 1, 0, VKD3DSIH_TEXKILL, {1 ,0}, { 3, 0}},
{VKD3D_SM1_OP_TEX, 1, 0, VKD3DSIH_TEX, {0, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEX, {1, 4}, { 1, 4}},
{VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEX, {2, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_TEXBEM, 1, 1, VKD3DSIH_TEXBEM, {0, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXBEML, 1, 1, VKD3DSIH_TEXBEML, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXREG2AR, 1, 1, VKD3DSIH_TEXREG2AR, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXREG2GB, 1, 1, VKD3DSIH_TEXREG2GB, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXREG2RGB, 1, 1, VKD3DSIH_TEXREG2RGB, {1, 2}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x2PAD, 1, 1, VKD3DSIH_TEXM3x2PAD, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x2TEX, 1, 1, VKD3DSIH_TEXM3x2TEX, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x3PAD, 1, 1, VKD3DSIH_TEXM3x3PAD, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x3DIFF, 1, 1, VKD3DSIH_TEXM3x3DIFF, {0, 0}, { 0, 0}},
{VKD3D_SM1_OP_TEXM3x3SPEC, 1, 2, VKD3DSIH_TEXM3x3SPEC, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x3VSPEC, 1, 1, VKD3DSIH_TEXM3x3VSPEC, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x3TEX, 1, 1, VKD3DSIH_TEXM3x3TEX, {1, 0}, { 1, 3}},
{VKD3D_SM1_OP_TEXDP3TEX, 1, 1, VKD3DSIH_TEXDP3TEX, {1, 2}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x2DEPTH, 1, 1, VKD3DSIH_TEXM3x2DEPTH, {1, 3}, { 1, 3}},
{VKD3D_SM1_OP_TEXDP3, 1, 1, VKD3DSIH_TEXDP3, {1, 2}, { 1, 3}},
{VKD3D_SM1_OP_TEXM3x3, 1, 1, VKD3DSIH_TEXM3x3, {1, 2}, { 1, 3}},
{VKD3D_SM1_OP_TEXDEPTH, 1, 0, VKD3DSIH_TEXDEPTH, {1, 4}, { 1, 4}},
{VKD3D_SM1_OP_BEM, 1, 2, VKD3DSIH_BEM, {1, 4}, { 1, 4}},
{VKD3D_SM1_OP_DSX, 1, 1, VKD3DSIH_DSX, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_DSY, 1, 1, VKD3DSIH_DSY, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_TEXLDD, 1, 4, VKD3DSIH_TEXLDD, {2, 1}, {~0u, ~0u}},
{VKD3D_SM1_OP_SETP, 1, 2, VKD3DSIH_SETP},
{VKD3D_SM1_OP_TEXLDL, 1, 2, VKD3DSIH_TEXLDL, {3, 0}, {~0u, ~0u}},
{VKD3D_SM1_OP_PHASE, 0, 0, VKD3DSIH_PHASE},
{0, 0, 0, VKD3DSIH_INVALID},
};
static const enum vkd3d_shader_resource_type resource_type_table[] =
{
/* VKD3D_SM1_RESOURCE_UNKNOWN */ VKD3D_SHADER_RESOURCE_NONE,
/* VKD3D_SM1_RESOURCE_TEXTURE_1D */ VKD3D_SHADER_RESOURCE_TEXTURE_1D,
/* VKD3D_SM1_RESOURCE_TEXTURE_2D */ VKD3D_SHADER_RESOURCE_TEXTURE_2D,
/* VKD3D_SM1_RESOURCE_TEXTURE_CUBE */ VKD3D_SHADER_RESOURCE_TEXTURE_CUBE,
/* VKD3D_SM1_RESOURCE_TEXTURE_3D */ VKD3D_SHADER_RESOURCE_TEXTURE_3D,
};
static struct vkd3d_shader_sm1_parser *vkd3d_shader_sm1_parser(struct vkd3d_shader_parser *parser)
{
return CONTAINING_RECORD(parser, struct vkd3d_shader_sm1_parser, p);
}
static uint32_t read_u32(const uint32_t **ptr)
{
return *(*ptr)++;
}
static bool shader_ver_ge(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
{
return v->major > major || (v->major == major && v->minor >= minor);
}
static bool shader_ver_le(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
{
return v->major < major || (v->major == major && v->minor <= minor);
}
static bool has_relative_address(uint32_t param)
{
enum vkd3d_sm1_address_mode_type address_mode;
address_mode = (param & VKD3D_SM1_ADDRESS_MODE_MASK) >> VKD3D_SM1_ADDRESS_MODE_SHIFT;
return address_mode == VKD3D_SM1_ADDRESS_MODE_RELATIVE;
}
static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info(
const struct vkd3d_shader_sm1_parser *sm1, enum vkd3d_sm1_opcode opcode)
{
const struct vkd3d_sm1_opcode_info *info;
unsigned int i = 0;
for (;;)
{
info = &sm1->opcode_table[i++];
if (info->vkd3d_opcode == VKD3DSIH_INVALID)
return NULL;
if (opcode == info->sm1_opcode
&& shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor)
&& (shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor)
|| !info->max_version.major))
return info;
}
}
static unsigned int shader_sm1_get_swizzle_component(uint32_t swizzle, unsigned int idx)
{
return (swizzle & VKD3D_SM1_SWIZZLE_COMPONENT_MASK(idx)) >> VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(idx);
}
static uint32_t swizzle_from_sm1(uint32_t swizzle)
{
return vkd3d_shader_create_swizzle(shader_sm1_get_swizzle_component(swizzle, 0),
shader_sm1_get_swizzle_component(swizzle, 1),
shader_sm1_get_swizzle_component(swizzle, 2),
shader_sm1_get_swizzle_component(swizzle, 3));
}
static void shader_sm1_parse_src_param(uint32_t param, const struct vkd3d_shader_src_param *rel_addr,
struct vkd3d_shader_src_param *src)
{
src->reg.type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT)
| ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2);
src->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
src->reg.non_uniform = false;
src->reg.data_type = VKD3D_DATA_FLOAT;
src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
src->reg.idx[0].rel_addr = rel_addr;
src->reg.idx[1].offset = ~0u;
src->reg.idx[1].rel_addr = NULL;
src->reg.idx[2].offset = ~0u;
src->reg.idx[2].rel_addr = NULL;
src->swizzle = swizzle_from_sm1((param & VKD3D_SM1_SWIZZLE_MASK) >> VKD3D_SM1_SWIZZLE_SHIFT);
src->modifiers = (param & VKD3D_SM1_SRC_MODIFIER_MASK) >> VKD3D_SM1_SRC_MODIFIER_SHIFT;
}
static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader_src_param *rel_addr,
struct vkd3d_shader_dst_param *dst)
{
dst->reg.type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT)
| ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2);
dst->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
dst->reg.non_uniform = false;
dst->reg.data_type = VKD3D_DATA_FLOAT;
dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK;
dst->reg.idx[0].rel_addr = rel_addr;
dst->reg.idx[1].offset = ~0u;
dst->reg.idx[1].rel_addr = NULL;
dst->reg.idx[2].offset = ~0u;
dst->reg.idx[2].rel_addr = NULL;
dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT;
dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT;
dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT;
}
/* Read a parameter token from the input stream, and possibly a relative
* addressing token. */
static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1,
const uint32_t **ptr, uint32_t *token, uint32_t *addr_token)
{
if (*ptr >= sm1->end)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Attempted to read a parameter token, but no more tokens are remaining.");
sm1->abort = true;
*token = 0;
return;
}
*token = read_u32(ptr);
if (!has_relative_address(*token))
return;
/* PS >= 3.0 have relative addressing (with token)
* VS >= 2.0 have relative addressing (with token)
* VS >= 1.0 < 2.0 have relative addressing (without token)
* The version check below should work in general. */
if (sm1->p.shader_version.major < 2)
{
*addr_token = (1u << 31)
| ((VKD3DSPR_ADDR << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2)
| ((VKD3DSPR_ADDR << VKD3D_SM1_REGISTER_TYPE_SHIFT) & VKD3D_SM1_REGISTER_TYPE_MASK)
| (VKD3D_SM1_SWIZZLE_DEFAULT << VKD3D_SM1_SWIZZLE_SHIFT);
return;
}
if (*ptr >= sm1->end)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Attempted to read an indirect addressing token, but no more tokens are remaining.");
sm1->abort = true;
*addr_token = 0;
return;
}
*addr_token = read_u32(ptr);
}
/* Skip the parameter tokens for an opcode. */
static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
const struct vkd3d_sm1_opcode_info *opcode_info, uint32_t opcode_token)
{
unsigned int length;
/* Version 2.0+ shaders may contain address tokens, but fortunately they
* have a useful length mask - use it here. Version 1.x shaders contain no
* such tokens. */
if (sm1->p.shader_version.major >= 2)
{
length = (opcode_token & VKD3D_SM1_INSTRUCTION_LENGTH_MASK) >> VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT;
*ptr += length;
return;
}
*ptr += (opcode_info->dst_count + opcode_info->src_count);
}
static void shader_sm1_destroy(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
free_shader_desc(&sm1->p.shader_desc);
vkd3d_free(sm1);
}
static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_src_param *src_param, struct vkd3d_shader_src_param *src_rel_addr)
{
uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
shader_sm1_parse_src_param(addr_token, NULL, src_rel_addr);
else
src_rel_addr = NULL;
shader_sm1_parse_src_param(token, src_rel_addr, src_param);
}
static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_dst_param *dst_param, struct vkd3d_shader_src_param *dst_rel_addr)
{
uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr);
else
dst_rel_addr = NULL;
shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param);
}
static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1,
const uint32_t **ptr, struct vkd3d_shader_semantic *semantic)
{
enum vkd3d_sm1_resource_type resource_type;
struct vkd3d_shader_register_range *range;
uint32_t usage_token, dst_token;
if (*ptr >= sm1->end || sm1->end - *ptr < 2)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Attempted to read a declaration instruction, but not enough tokens are remaining.");
sm1->abort = true;
return;
}
usage_token = read_u32(ptr);
dst_token = read_u32(ptr);
semantic->usage = (usage_token & VKD3D_SM1_DCL_USAGE_MASK) >> VKD3D_SM1_DCL_USAGE_SHIFT;
semantic->usage_idx = (usage_token & VKD3D_SM1_DCL_USAGE_INDEX_MASK) >> VKD3D_SM1_DCL_USAGE_INDEX_SHIFT;
resource_type = (usage_token & VKD3D_SM1_RESOURCE_TYPE_MASK) >> VKD3D_SM1_RESOURCE_TYPE_SHIFT;
if (resource_type >= ARRAY_SIZE(resource_type_table))
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE,
"Invalid resource type %#x.", resource_type);
semantic->resource_type = VKD3D_SHADER_RESOURCE_NONE;
}
else
{
semantic->resource_type = resource_type_table[resource_type];
}
semantic->resource_data_type[0] = VKD3D_DATA_FLOAT;
semantic->resource_data_type[1] = VKD3D_DATA_FLOAT;
semantic->resource_data_type[2] = VKD3D_DATA_FLOAT;
semantic->resource_data_type[3] = VKD3D_DATA_FLOAT;
shader_sm1_parse_dst_param(dst_token, NULL, &semantic->resource.reg);
range = &semantic->resource.range;
range->space = 0;
range->first = range->last = semantic->resource.reg.reg.idx[0].offset;
}
static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_src_param *src_param, enum vkd3d_immconst_type type, enum vkd3d_data_type data_type)
{
unsigned int count = type == VKD3D_IMMCONST_VEC4 ? 4 : 1;
if (*ptr >= sm1->end || sm1->end - *ptr < count)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Attempted to read a constant definition, but not enough tokens are remaining. "
"%zu token(s) available, %u required.", sm1->end - *ptr, count);
sm1->abort = true;
return;
}
src_param->reg.type = VKD3DSPR_IMMCONST;
src_param->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
src_param->reg.non_uniform = false;
src_param->reg.data_type = data_type;
src_param->reg.idx[0].offset = ~0u;
src_param->reg.idx[0].rel_addr = NULL;
src_param->reg.idx[1].offset = ~0u;
src_param->reg.idx[1].rel_addr = NULL;
src_param->reg.idx[2].offset = ~0u;
src_param->reg.idx[2].rel_addr = NULL;
src_param->reg.immconst_type = type;
memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t));
src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
src_param->modifiers = 0;
*ptr += count;
}
static void shader_sm1_read_comment(struct vkd3d_shader_sm1_parser *sm1)
{
const uint32_t **ptr = &sm1->p.ptr;
const char *comment;
unsigned int size;
size_t remaining;
uint32_t token;
if (*ptr >= sm1->end)
return;
remaining = sm1->end - *ptr;
token = **ptr;
while ((token & VKD3D_SM1_OPCODE_MASK) == VKD3D_SM1_OP_COMMENT)
{
size = (token & VKD3D_SM1_COMMENT_SIZE_MASK) >> VKD3D_SM1_COMMENT_SIZE_SHIFT;
if (size > --remaining)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Encountered a %u token comment, but only %zu token(s) is/are remaining.",
size, remaining);
return;
}
comment = (const char *)++(*ptr);
remaining -= size;
*ptr += size;
if (size > 1 && *(const uint32_t *)comment == TAG_TEXT)
{
const char *end = comment + size * sizeof(token);
const char *p = comment + sizeof(token);
const char *line;
TRACE("// TEXT\n");
for (line = p; line < end; line = p)
{
if (!(p = memchr(line, '\n', end - line)))
p = end;
else
++p;
TRACE("// %s\n", debugstr_an(line, p - line));
}
}
else if (size)
{
TRACE("// %s\n", debugstr_an(comment, size * sizeof(token)));
}
else
break;
if (!remaining)
break;
token = **ptr;
}
}
static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins)
{
if ((ins->handler_idx == VKD3DSIH_BREAKP || ins->handler_idx == VKD3DSIH_IF) && ins->flags)
{
vkd3d_shader_parser_warning(&sm1->p, VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS,
"Ignoring unexpected instruction flags %#x.", ins->flags);
ins->flags = 0;
}
}
static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
const struct vkd3d_sm1_opcode_info *opcode_info;
const uint32_t **ptr = &parser->ptr;
uint32_t opcode_token;
const uint32_t *p;
unsigned int i;
shader_sm1_read_comment(sm1);
if (*ptr >= sm1->end)
{
WARN("End of byte-code, failed to read opcode.\n");
goto fail;
}
++parser->location.line;
opcode_token = read_u32(ptr);
if (!(opcode_info = shader_sm1_get_opcode_info(sm1, opcode_token & VKD3D_SM1_OPCODE_MASK)))
{
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE,
"Invalid opcode %#x (token 0x%08x, shader version %u.%u).",
opcode_token & VKD3D_SM1_OPCODE_MASK, opcode_token,
sm1->p.shader_version.major, sm1->p.shader_version.minor);
goto fail;
}
ins->handler_idx = opcode_info->vkd3d_opcode;
ins->flags = (opcode_token & VKD3D_SM1_INSTRUCTION_FLAGS_MASK) >> VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
ins->coissue = opcode_token & VKD3D_SM1_COISSUE;
ins->raw = false;
ins->structured = false;
ins->predicate = opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED ? &sm1->pred_param : NULL;
ins->dst_count = opcode_info->dst_count;
ins->dst = &sm1->dst_param;
ins->src_count = opcode_info->src_count;
ins->src = sm1->src_param;
ins->resource_type = VKD3D_SHADER_RESOURCE_NONE;
ins->resource_stride = 0;
ins->resource_data_type[0] = VKD3D_DATA_FLOAT;
ins->resource_data_type[1] = VKD3D_DATA_FLOAT;
ins->resource_data_type[2] = VKD3D_DATA_FLOAT;
ins->resource_data_type[3] = VKD3D_DATA_FLOAT;
memset(&ins->texel_offset, 0, sizeof(ins->texel_offset));
p = *ptr;
shader_sm1_skip_opcode(sm1, ptr, opcode_info, opcode_token);
if (*ptr > sm1->end)
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"The current instruction ends %zu token(s) past the end of the shader.",
*ptr - sm1->end);
goto fail;
}
if (ins->handler_idx == VKD3DSIH_DCL)
{
shader_sm1_read_semantic(sm1, &p, &ins->declaration.semantic);
}
else if (ins->handler_idx == VKD3DSIH_DEF)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT);
}
else if (ins->handler_idx == VKD3DSIH_DEFB)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT);
}
else if (ins->handler_idx == VKD3DSIH_DEFI)
{
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT);
}
else
{
/* Destination token */
if (ins->dst_count)
shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr);
/* Predication token */
if (ins->predicate)
shader_sm1_read_src_param(sm1, &p, &sm1->pred_param, &sm1->pred_rel_addr);
/* Other source tokens */
for (i = 0; i < ins->src_count; ++i)
shader_sm1_read_src_param(sm1, &p, &sm1->src_param[i], &sm1->src_rel_addr[i]);
}
if (sm1->abort)
{
sm1->abort = false;
goto fail;
}
shader_sm1_validate_instruction(sm1, ins);
return;
fail:
ins->handler_idx = VKD3DSIH_INVALID;
*ptr = sm1->end;
}
static bool shader_sm1_is_end(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
const uint32_t **ptr = &parser->ptr;
shader_sm1_read_comment(sm1);
if (*ptr >= sm1->end)
return true;
if (**ptr == VKD3D_SM1_END)
{
++(*ptr);
return true;
}
return false;
}
static void shader_sm1_reset(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
parser->ptr = sm1->start;
parser->failed = false;
}
const struct vkd3d_shader_parser_ops shader_sm1_parser_ops =
{
.parser_reset = shader_sm1_reset,
.parser_destroy = shader_sm1_destroy,
.parser_read_instruction = shader_sm1_read_instruction,
.parser_is_end = shader_sm1_is_end,
};
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
{
const struct vkd3d_shader_location location = {.source_name = compile_info->source_name};
const uint32_t *code = compile_info->source.code;
size_t code_size = compile_info->source.size;
struct vkd3d_shader_desc *shader_desc;
struct vkd3d_shader_version version;
uint16_t shader_type;
size_t token_count;
token_count = code_size / sizeof(*sm1->start);
if (token_count < 2)
{
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF,
"Invalid shader size %zu (token count %zu). At least 2 tokens are required.",
code_size, token_count);
return VKD3D_ERROR_INVALID_SHADER;
}
TRACE("Version: 0x%08x.\n", code[0]);
shader_type = code[0] >> 16;
version.major = VKD3D_SM1_VERSION_MAJOR(code[0]);
version.minor = VKD3D_SM1_VERSION_MINOR(code[0]);
switch (shader_type)
{
case VKD3D_SM1_VS:
version.type = VKD3D_SHADER_TYPE_VERTEX;
sm1->opcode_table = vs_opcode_table;
break;
case VKD3D_SM1_PS:
version.type = VKD3D_SHADER_TYPE_PIXEL;
sm1->opcode_table = ps_opcode_table;
break;
default:
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN,
"Invalid shader type %#x (token 0x%08x).", shader_type, code[0]);
return VKD3D_ERROR_INVALID_SHADER;
}
if (!shader_ver_le(&version, 3, 0))
{
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN,
"Invalid shader version %u.%u (token 0x%08x).", version.major, version.minor, code[0]);
return VKD3D_ERROR_INVALID_SHADER;
}
sm1->start = &code[1];
sm1->end = &code[token_count];
vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops);
shader_desc = &sm1->p.shader_desc;
shader_desc->byte_code = code;
shader_desc->byte_code_size = code_size;
sm1->p.ptr = sm1->start;
return VKD3D_OK;
}
int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
{
struct vkd3d_shader_sm1_parser *sm1;
int ret;
if (!(sm1 = vkd3d_calloc(1, sizeof(*sm1))))
{
ERR("Failed to allocate parser.\n");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
if ((ret = shader_sm1_init(sm1, compile_info, message_context)) < 0)
{
WARN("Failed to initialise shader parser, ret %d.\n", ret);
vkd3d_free(sm1);
return ret;
}
*parser = &sm1->p;
return VKD3D_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/*
* Copyright 2021 Atharva Nimbalkar
*
* 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_shader_private.h"
struct vkd3d_glsl_generator
{
struct vkd3d_shader_version version;
struct vkd3d_string_buffer buffer;
const struct vkd3d_shader_location *location;
struct vkd3d_shader_message_context *message_context;
bool failed;
};
struct vkd3d_glsl_generator *vkd3d_glsl_generator_create(const struct vkd3d_shader_version *version,
struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location)
{
struct vkd3d_glsl_generator *generator;
if (!(generator = vkd3d_malloc(sizeof(*generator))))
return NULL;
memset(generator, 0, sizeof(*generator));
generator->version = *version;
vkd3d_string_buffer_init(&generator->buffer);
generator->location = location;
generator->message_context = message_context;
return generator;
}
static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
struct vkd3d_glsl_generator *generator,
enum vkd3d_shader_error error, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vkd3d_shader_verror(generator->message_context, generator->location, error, fmt, args);
va_end(args);
generator->failed = true;
}
static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
const struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_version *version = &generator->version;
/*
* TODO: Implement in_subroutine
* TODO: shader_glsl_generate_shader_epilogue(generator);
*/
if (version->major >= 4)
{
vkd3d_string_buffer_printf(&generator->buffer, "return;\n");
}
}
static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator,
const struct vkd3d_shader_instruction *instruction)
{
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_INPUT:
case VKD3DSIH_DCL_OUTPUT:
case VKD3DSIH_DCL_OUTPUT_SIV:
break;
case VKD3DSIH_RET:
shader_glsl_ret(generator, instruction);
break;
default:
vkd3d_glsl_compiler_error(generator,
VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Unhandled instruction %#x", instruction->handler_idx);
break;
}
}
int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out)
{
void *code;
struct vkd3d_shader_instruction ins;
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n");
vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
while (!vkd3d_shader_parser_is_end(parser))
{
vkd3d_shader_parser_read_instruction(parser, &ins);
if (ins.handler_idx == VKD3DSIH_INVALID)
{
vkd3d_glsl_compiler_error(generator,
VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Encountered unrecognized or invalid instruction.");
break;
}
vkd3d_glsl_handle_instruction(generator, &ins);
}
if (parser->failed || generator->failed)
return VKD3D_ERROR_INVALID_SHADER;
vkd3d_string_buffer_printf(&generator->buffer, "}\n");
if ((code = vkd3d_malloc(generator->buffer.buffer_size)))
{
memcpy(code, generator->buffer.buffer, generator->buffer.content_size);
out->size = generator->buffer.content_size;
out->code = code;
}
else return VKD3D_ERROR_OUT_OF_MEMORY;
return VKD3D_OK;
}
void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator)
{
vkd3d_string_buffer_cleanup(&generator->buffer);
vkd3d_free(generator);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,814 @@
/*
* Copyright 2012 Matteo Bruni for CodeWeavers
* Copyright 2019-2020 Zebediah Figura 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_SHADER_HLSL_H
#define __VKD3D_SHADER_HLSL_H
#include "vkd3d_shader_private.h"
#include "wine/rbtree.h"
#include "d3dcommon.h"
#include "d3dx9shader.h"
#include "sm4.h"
/* The general IR structure is inspired by Mesa GLSL hir, even though the code
* ends up being quite different in practice. Anyway, here comes the relevant
* licensing information.
*
* Copyright © 2010 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#define HLSL_SWIZZLE_X (0u)
#define HLSL_SWIZZLE_Y (1u)
#define HLSL_SWIZZLE_Z (2u)
#define HLSL_SWIZZLE_W (3u)
#define HLSL_SWIZZLE(x, y, z, w) \
(((HLSL_SWIZZLE_ ## x) << 0) \
| ((HLSL_SWIZZLE_ ## y) << 2) \
| ((HLSL_SWIZZLE_ ## z) << 4) \
| ((HLSL_SWIZZLE_ ## w) << 6))
enum hlsl_type_class
{
HLSL_CLASS_SCALAR,
HLSL_CLASS_VECTOR,
HLSL_CLASS_MATRIX,
HLSL_CLASS_LAST_NUMERIC = HLSL_CLASS_MATRIX,
HLSL_CLASS_STRUCT,
HLSL_CLASS_ARRAY,
HLSL_CLASS_OBJECT,
};
enum hlsl_base_type
{
HLSL_TYPE_FLOAT,
HLSL_TYPE_HALF,
HLSL_TYPE_DOUBLE,
HLSL_TYPE_INT,
HLSL_TYPE_UINT,
HLSL_TYPE_BOOL,
HLSL_TYPE_LAST_SCALAR = HLSL_TYPE_BOOL,
HLSL_TYPE_SAMPLER,
HLSL_TYPE_TEXTURE,
HLSL_TYPE_PIXELSHADER,
HLSL_TYPE_VERTEXSHADER,
HLSL_TYPE_STRING,
HLSL_TYPE_VOID,
};
enum hlsl_sampler_dim
{
HLSL_SAMPLER_DIM_GENERIC,
HLSL_SAMPLER_DIM_1D,
HLSL_SAMPLER_DIM_2D,
HLSL_SAMPLER_DIM_3D,
HLSL_SAMPLER_DIM_CUBE,
HLSL_SAMPLER_DIM_LAST_SAMPLER = HLSL_SAMPLER_DIM_CUBE,
HLSL_SAMPLER_DIM_1DARRAY,
HLSL_SAMPLER_DIM_2DARRAY,
HLSL_SAMPLER_DIM_2DMS,
HLSL_SAMPLER_DIM_2DMSARRAY,
HLSL_SAMPLER_DIM_CUBEARRAY,
HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_CUBEARRAY,
};
enum hlsl_matrix_majority
{
HLSL_COLUMN_MAJOR,
HLSL_ROW_MAJOR
};
struct hlsl_type
{
struct list entry;
struct rb_entry scope_entry;
enum hlsl_type_class type;
enum hlsl_base_type base_type;
enum hlsl_sampler_dim sampler_dim;
const char *name;
unsigned int modifiers;
unsigned int dimx;
unsigned int dimy;
union
{
struct list *elements;
struct
{
struct hlsl_type *type;
unsigned int elements_count;
} array;
struct hlsl_type *resource_format;
} e;
unsigned int reg_size;
size_t bytecode_offset;
};
struct hlsl_semantic
{
const char *name;
uint32_t index;
};
struct hlsl_struct_field
{
struct list entry;
struct vkd3d_shader_location loc;
struct hlsl_type *type;
const char *name;
struct hlsl_semantic semantic;
unsigned int reg_offset;
size_t name_bytecode_offset;
};
struct hlsl_reg
{
uint32_t id;
unsigned int writemask;
bool allocated;
};
enum hlsl_ir_node_type
{
HLSL_IR_CONSTANT,
HLSL_IR_EXPR,
HLSL_IR_IF,
HLSL_IR_LOAD,
HLSL_IR_LOOP,
HLSL_IR_JUMP,
HLSL_IR_RESOURCE_LOAD,
HLSL_IR_STORE,
HLSL_IR_SWIZZLE,
};
struct hlsl_ir_node
{
struct list entry;
enum hlsl_ir_node_type type;
struct hlsl_type *data_type;
struct list uses;
struct vkd3d_shader_location loc;
/* Liveness ranges. "index" is the index of this instruction. Since this is
* essentially an SSA value, the earliest live point is the index. This is
* true even for loops, since currently we can't have a reference to a
* value generated in an earlier iteration of the loop. */
unsigned int index, last_read;
struct hlsl_reg reg;
};
struct hlsl_block
{
struct list instrs;
};
struct hlsl_src
{
struct hlsl_ir_node *node;
struct list entry;
};
#define HLSL_STORAGE_EXTERN 0x00000001
#define HLSL_STORAGE_NOINTERPOLATION 0x00000002
#define HLSL_MODIFIER_PRECISE 0x00000004
#define HLSL_STORAGE_SHARED 0x00000008
#define HLSL_STORAGE_GROUPSHARED 0x00000010
#define HLSL_STORAGE_STATIC 0x00000020
#define HLSL_STORAGE_UNIFORM 0x00000040
#define HLSL_STORAGE_VOLATILE 0x00000080
#define HLSL_MODIFIER_CONST 0x00000100
#define HLSL_MODIFIER_ROW_MAJOR 0x00000200
#define HLSL_MODIFIER_COLUMN_MAJOR 0x00000400
#define HLSL_STORAGE_IN 0x00000800
#define HLSL_STORAGE_OUT 0x00001000
#define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_STORAGE_VOLATILE | \
HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \
HLSL_MODIFIER_COLUMN_MAJOR)
#define HLSL_MODIFIERS_MAJORITY_MASK (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR)
struct hlsl_reg_reservation
{
char type;
unsigned int index;
};
struct hlsl_ir_var
{
struct hlsl_type *data_type;
struct vkd3d_shader_location loc;
const char *name;
struct hlsl_semantic semantic;
struct hlsl_buffer *buffer;
unsigned int modifiers;
struct hlsl_reg_reservation reg_reservation;
struct list scope_entry, param_entry, extern_entry;
unsigned int first_write, last_read;
unsigned int buffer_offset;
struct hlsl_reg reg;
uint32_t is_input_semantic : 1;
uint32_t is_output_semantic : 1;
uint32_t is_uniform : 1;
uint32_t is_param : 1;
};
struct hlsl_ir_function
{
struct rb_entry entry;
const char *name;
struct rb_tree overloads;
bool intrinsic;
};
struct hlsl_ir_function_decl
{
struct hlsl_type *return_type;
struct hlsl_ir_var *return_var;
struct vkd3d_shader_location loc;
struct rb_entry entry;
struct hlsl_ir_function *func;
struct list *parameters;
struct hlsl_block body;
bool has_body;
};
struct hlsl_ir_if
{
struct hlsl_ir_node node;
struct hlsl_src condition;
struct hlsl_block then_instrs;
struct hlsl_block else_instrs;
};
struct hlsl_ir_loop
{
struct hlsl_ir_node node;
/* loop condition is stored in the body (as "if (!condition) break;") */
struct hlsl_block body;
unsigned int next_index; /* liveness index of the end of the loop */
};
enum hlsl_ir_expr_op
{
HLSL_OP1_ABS,
HLSL_OP1_BIT_NOT,
HLSL_OP1_CAST,
HLSL_OP1_COS,
HLSL_OP1_COS_REDUCED, /* Reduced range [-pi, pi] */
HLSL_OP1_DSX,
HLSL_OP1_DSY,
HLSL_OP1_EXP2,
HLSL_OP1_FLOOR,
HLSL_OP1_FRACT,
HLSL_OP1_LOG2,
HLSL_OP1_LOGIC_NOT,
HLSL_OP1_NEG,
HLSL_OP1_NRM,
HLSL_OP1_RCP,
HLSL_OP1_ROUND,
HLSL_OP1_RSQ,
HLSL_OP1_SAT,
HLSL_OP1_SIGN,
HLSL_OP1_SIN,
HLSL_OP1_SIN_REDUCED, /* Reduced range [-pi, pi] */
HLSL_OP1_SQRT,
HLSL_OP2_ADD,
HLSL_OP2_BIT_AND,
HLSL_OP2_BIT_OR,
HLSL_OP2_BIT_XOR,
HLSL_OP2_CRS,
HLSL_OP2_DIV,
HLSL_OP2_DOT,
HLSL_OP2_EQUAL,
HLSL_OP2_GEQUAL,
HLSL_OP2_LESS,
HLSL_OP2_LOGIC_AND,
HLSL_OP2_LOGIC_OR,
HLSL_OP2_LSHIFT,
HLSL_OP2_MAX,
HLSL_OP2_MIN,
HLSL_OP2_MOD,
HLSL_OP2_MUL,
HLSL_OP2_NEQUAL,
HLSL_OP2_RSHIFT,
HLSL_OP3_LERP,
};
#define HLSL_MAX_OPERANDS 3
struct hlsl_ir_expr
{
struct hlsl_ir_node node;
enum hlsl_ir_expr_op op;
struct hlsl_src operands[HLSL_MAX_OPERANDS];
};
enum hlsl_ir_jump_type
{
HLSL_IR_JUMP_BREAK,
HLSL_IR_JUMP_CONTINUE,
HLSL_IR_JUMP_DISCARD,
HLSL_IR_JUMP_RETURN,
};
struct hlsl_ir_jump
{
struct hlsl_ir_node node;
enum hlsl_ir_jump_type type;
};
struct hlsl_ir_swizzle
{
struct hlsl_ir_node node;
struct hlsl_src val;
DWORD swizzle;
};
struct hlsl_deref
{
struct hlsl_ir_var *var;
struct hlsl_src offset;
};
struct hlsl_ir_load
{
struct hlsl_ir_node node;
struct hlsl_deref src;
};
enum hlsl_resource_load_type
{
HLSL_RESOURCE_LOAD,
HLSL_RESOURCE_SAMPLE,
HLSL_RESOURCE_GATHER_RED,
HLSL_RESOURCE_GATHER_GREEN,
HLSL_RESOURCE_GATHER_BLUE,
HLSL_RESOURCE_GATHER_ALPHA,
};
struct hlsl_ir_resource_load
{
struct hlsl_ir_node node;
enum hlsl_resource_load_type load_type;
struct hlsl_deref resource, sampler;
struct hlsl_src coords;
struct hlsl_src texel_offset;
};
struct hlsl_ir_store
{
struct hlsl_ir_node node;
struct hlsl_deref lhs;
struct hlsl_src rhs;
unsigned char writemask;
};
struct hlsl_ir_constant
{
struct hlsl_ir_node node;
union hlsl_constant_value
{
uint32_t u;
int32_t i;
float f;
double d;
bool b;
} value[4];
struct hlsl_reg reg;
};
struct hlsl_scope
{
struct list entry;
struct list vars;
struct rb_tree types;
struct hlsl_scope *upper;
};
struct hlsl_profile_info
{
const char *name;
enum vkd3d_shader_type type;
unsigned int major_version;
unsigned int minor_version;
unsigned int major_level;
unsigned int minor_level;
bool software;
};
struct hlsl_vec4
{
float f[4];
};
enum hlsl_buffer_type
{
HLSL_BUFFER_CONSTANT,
HLSL_BUFFER_TEXTURE,
};
struct hlsl_buffer
{
struct vkd3d_shader_location loc;
enum hlsl_buffer_type type;
const char *name;
struct hlsl_reg_reservation reservation;
struct list entry;
unsigned size, used_size;
struct hlsl_reg reg;
};
struct hlsl_ctx
{
const struct hlsl_profile_info *profile;
const char **source_files;
unsigned int source_files_count;
struct vkd3d_shader_location location;
struct vkd3d_shader_message_context *message_context;
struct vkd3d_string_buffer_cache string_buffers;
int result;
void *scanner;
struct hlsl_scope *cur_scope;
struct hlsl_scope *globals;
struct list scopes;
struct list extern_vars;
struct list buffers;
struct hlsl_buffer *cur_buffer, *globals_buffer, *params_buffer;
struct list types;
struct rb_tree functions;
const struct hlsl_ir_function_decl *cur_function;
enum hlsl_matrix_majority matrix_majority;
struct
{
struct hlsl_type *scalar[HLSL_TYPE_LAST_SCALAR + 1];
struct hlsl_type *vector[HLSL_TYPE_LAST_SCALAR + 1][4];
/* matrix[float][2][4] is a float4x2, i.e. dimx = 2, dimy = 4 */
struct hlsl_type *matrix[HLSL_TYPE_LAST_SCALAR + 1][4][4];
struct hlsl_type *sampler[HLSL_SAMPLER_DIM_LAST_SAMPLER + 1];
struct hlsl_type *Void;
} builtin_types;
struct list static_initializers;
struct hlsl_constant_defs
{
struct hlsl_vec4 *values;
size_t count, size;
} constant_defs;
uint32_t temp_count;
uint32_t in_state_block : 1;
};
enum hlsl_error_level
{
HLSL_LEVEL_ERROR = 0,
HLSL_LEVEL_WARNING,
HLSL_LEVEL_NOTE,
};
static inline struct hlsl_ir_constant *hlsl_ir_constant(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_CONSTANT);
return CONTAINING_RECORD(node, struct hlsl_ir_constant, node);
}
static inline struct hlsl_ir_expr *hlsl_ir_expr(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_EXPR);
return CONTAINING_RECORD(node, struct hlsl_ir_expr, node);
}
static inline struct hlsl_ir_if *hlsl_ir_if(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_IF);
return CONTAINING_RECORD(node, struct hlsl_ir_if, node);
}
static inline struct hlsl_ir_jump *hlsl_ir_jump(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_JUMP);
return CONTAINING_RECORD(node, struct hlsl_ir_jump, node);
}
static inline struct hlsl_ir_load *hlsl_ir_load(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_LOAD);
return CONTAINING_RECORD(node, struct hlsl_ir_load, node);
}
static inline struct hlsl_ir_loop *hlsl_ir_loop(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_LOOP);
return CONTAINING_RECORD(node, struct hlsl_ir_loop, node);
}
static inline struct hlsl_ir_resource_load *hlsl_ir_resource_load(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_RESOURCE_LOAD);
return CONTAINING_RECORD(node, struct hlsl_ir_resource_load, node);
}
static inline struct hlsl_ir_store *hlsl_ir_store(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_STORE);
return CONTAINING_RECORD(node, struct hlsl_ir_store, node);
}
static inline struct hlsl_ir_swizzle *hlsl_ir_swizzle(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_SWIZZLE);
return CONTAINING_RECORD(node, struct hlsl_ir_swizzle, node);
}
static inline void init_node(struct hlsl_ir_node *node, enum hlsl_ir_node_type type,
struct hlsl_type *data_type, struct vkd3d_shader_location loc)
{
memset(node, 0, sizeof(*node));
node->type = type;
node->data_type = data_type;
node->loc = loc;
list_init(&node->uses);
}
static inline void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node)
{
src->node = node;
if (node)
list_add_tail(&node->uses, &src->entry);
}
static inline void hlsl_src_remove(struct hlsl_src *src)
{
if (src->node)
list_remove(&src->entry);
src->node = NULL;
}
static inline void *hlsl_alloc(struct hlsl_ctx *ctx, size_t size)
{
void *ptr = vkd3d_calloc(1, size);
if (!ptr)
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return ptr;
}
static inline void *hlsl_realloc(struct hlsl_ctx *ctx, void *ptr, size_t size)
{
void *ret = vkd3d_realloc(ptr, size);
if (!ret)
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return ret;
}
static inline char *hlsl_strdup(struct hlsl_ctx *ctx, const char *string)
{
char *ptr = vkd3d_strdup(string);
if (!ptr)
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return ptr;
}
static inline bool hlsl_array_reserve(struct hlsl_ctx *ctx, void **elements,
size_t *capacity, size_t element_count, size_t element_size)
{
bool ret = vkd3d_array_reserve(elements, capacity, element_count, element_size);
if (!ret)
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return ret;
}
static inline struct vkd3d_string_buffer *hlsl_get_string_buffer(struct hlsl_ctx *ctx)
{
struct vkd3d_string_buffer *ret = vkd3d_string_buffer_get(&ctx->string_buffers);
if (!ret)
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return ret;
}
static inline void hlsl_release_string_buffer(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer)
{
vkd3d_string_buffer_release(&ctx->string_buffers, buffer);
}
static inline struct hlsl_type *hlsl_get_scalar_type(const struct hlsl_ctx *ctx, enum hlsl_base_type base_type)
{
return ctx->builtin_types.scalar[base_type];
}
static inline struct hlsl_type *hlsl_get_vector_type(const struct hlsl_ctx *ctx, enum hlsl_base_type base_type,
unsigned int dimx)
{
return ctx->builtin_types.vector[base_type][dimx - 1];
}
static inline struct hlsl_type *hlsl_get_matrix_type(const struct hlsl_ctx *ctx, enum hlsl_base_type base_type,
unsigned int dimx, unsigned int dimy)
{
return ctx->builtin_types.matrix[base_type][dimx - 1][dimy - 1];
}
static inline struct hlsl_type *hlsl_get_numeric_type(const struct hlsl_ctx *ctx, enum hlsl_type_class type,
enum hlsl_base_type base_type, unsigned int dimx, unsigned int dimy)
{
if (type == HLSL_CLASS_SCALAR)
return hlsl_get_scalar_type(ctx, base_type);
else if (type == HLSL_CLASS_VECTOR)
return hlsl_get_vector_type(ctx, base_type, dimx);
else
return hlsl_get_matrix_type(ctx, base_type, dimx, dimy);
}
static inline unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim)
{
switch (dim)
{
case HLSL_SAMPLER_DIM_1D:
return 1;
case HLSL_SAMPLER_DIM_1DARRAY:
case HLSL_SAMPLER_DIM_2D:
case HLSL_SAMPLER_DIM_2DMS:
return 2;
case HLSL_SAMPLER_DIM_2DARRAY:
case HLSL_SAMPLER_DIM_2DMSARRAY:
case HLSL_SAMPLER_DIM_3D:
case HLSL_SAMPLER_DIM_CUBE:
return 3;
case HLSL_SAMPLER_DIM_CUBEARRAY:
return 4;
default:
assert(0);
return 0;
}
}
const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op);
const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type);
const char *debug_hlsl_writemask(unsigned int writemask);
const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int count);
struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const struct hlsl_type *type);
struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers);
const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type);
void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function_decl *decl, bool intrinsic);
bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var);
void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func);
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out);
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
void hlsl_free_instr(struct hlsl_ir_node *node);
void hlsl_free_instr_list(struct list *list);
void hlsl_free_type(struct hlsl_type *type);
void hlsl_free_var(struct hlsl_ir_var *decl);
bool hlsl_get_function(struct hlsl_ctx *ctx, const char *name);
struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name);
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive);
struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size);
struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1,
struct hlsl_ir_node *arg2);
struct hlsl_buffer *hlsl_new_buffer(struct hlsl_ctx *ctx, enum hlsl_buffer_type type, const char *name,
const struct hlsl_reg_reservation *reservation, struct vkd3d_shader_location loc);
struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_type *type,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ctx *ctx, struct hlsl_ir_node *node);
struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type,
struct list *parameters, const struct hlsl_semantic *semantic, struct vkd3d_shader_location loc);
struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, struct vkd3d_shader_location loc);
struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n,
const struct vkd3d_shader_location loc);
struct hlsl_ir_jump *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc);
struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
struct hlsl_type *type, struct vkd3d_shader_location loc);
struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc);
struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type,
enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset,
struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords,
struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc);
struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs);
struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset,
struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc);
struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, struct list *fields);
struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components,
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
const struct vkd3d_shader_location loc);
struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format);
struct hlsl_ir_constant *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n,
const struct vkd3d_shader_location loc);
struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg,
struct vkd3d_shader_location loc);
struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers,
const struct hlsl_reg_reservation *reg_reservation);
struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
const struct vkd3d_shader_location loc);
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
void hlsl_fixme(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4);
void hlsl_warning(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
void hlsl_note(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_log_level level, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
void hlsl_push_scope(struct hlsl_ctx *ctx);
void hlsl_pop_scope(struct hlsl_ctx *ctx);
bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type);
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
unsigned int default_majority, unsigned int modifiers);
unsigned int hlsl_type_component_count(struct hlsl_type *type);
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset);
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);
unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim);
unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second);
unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask);
unsigned int hlsl_swizzle_from_writemask(unsigned int writemask);
bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset);
unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl_deref *deref);
struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
const struct hlsl_type *type);
bool hlsl_fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg);
bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx);
int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx,
const struct hlsl_semantic *semantic, bool output, D3D_NAME *usage);
bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
bool output, enum vkd3d_sm4_register_type *type, enum vkd3d_sm4_swizzle_type *swizzle_type, bool *has_idx);
int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl);
#endif

View File

@ -0,0 +1,305 @@
/*
* HLSL parser
*
* Copyright 2008 Stefan Dösinger
* Copyright 2012 Matteo Bruni 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
*/
%{
#define YY_NO_UNISTD_H
#include "hlsl.h"
#include "hlsl.tab.h"
#define YYSTYPE HLSL_YYSTYPE
#define YYLTYPE HLSL_YYLTYPE
static void update_location(struct hlsl_ctx *ctx, YYLTYPE *loc);
#define YY_USER_ACTION update_location(yyget_extra(yyscanner), yyget_lloc(yyscanner));
%}
%option bison-bridge
%option bison-locations
%option extra-type="struct hlsl_ctx *"
%option never-interactive
%option noinput
%option nounput
%option noyywrap
%option prefix="hlsl_yy"
%option reentrant
%x pp pp_line pp_pragma pp_ignore
RESERVED1 auto|case|catch|char|class|const_cast|default|delete|dynamic_cast|enum
RESERVED2 explicit|friend|goto|long|mutable|new|operator|private|protected|public
RESERVED3 reinterpret_cast|short|signed|sizeof|static_cast|template|this|throw|try
RESERVED4 typename|union|unsigned|using|virtual
WS [ \t]
NEWLINE (\n)|(\r\n)
DOUBLESLASHCOMMENT "//"[^\n]*
STRING \"[^\"]*\"
IDENTIFIER [A-Za-z_][A-Za-z0-9_]*
ANY (.)
%%
{RESERVED1} |
{RESERVED2} |
{RESERVED3} |
{RESERVED4} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
hlsl_error(ctx, yylloc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
"Reserved keyword \"%s\" used.", yytext);
}
BlendState {return KW_BLENDSTATE; }
break {return KW_BREAK; }
Buffer {return KW_BUFFER; }
cbuffer {return KW_CBUFFER; }
compile {return KW_COMPILE; }
const {return KW_CONST; }
continue {return KW_CONTINUE; }
DepthStencilState {return KW_DEPTHSTENCILSTATE; }
DepthStencilView {return KW_DEPTHSTENCILVIEW; }
discard {return KW_DISCARD; }
do {return KW_DO; }
double {return KW_DOUBLE; }
else {return KW_ELSE; }
extern {return KW_EXTERN; }
false {return KW_FALSE; }
for {return KW_FOR; }
GeometryShader {return KW_GEOMETRYSHADER; }
groupshared {return KW_GROUPSHARED; }
if {return KW_IF; }
in {return KW_IN; }
inline {return KW_INLINE; }
inout {return KW_INOUT; }
matrix {return KW_MATRIX; }
namespace {return KW_NAMESPACE; }
nointerpolation {return KW_NOINTERPOLATION; }
out {return KW_OUT; }
pass {return KW_PASS; }
PixelShader {return KW_PIXELSHADER; }
precise {return KW_PRECISE; }
RasterizerState {return KW_RASTERIZERSTATE; }
RenderTargetView {return KW_RENDERTARGETVIEW; }
return {return KW_RETURN; }
register {return KW_REGISTER; }
sampler {return KW_SAMPLER; }
sampler1D {return KW_SAMPLER1D; }
sampler2D {return KW_SAMPLER2D; }
sampler3D {return KW_SAMPLER3D; }
samplerCUBE {return KW_SAMPLERCUBE; }
sampler_state {return KW_SAMPLER_STATE; }
SamplerComparisonState {return KW_SAMPLERCOMPARISONSTATE;}
SamplerState {return KW_SAMPLER; }
shared {return KW_SHARED; }
stateblock {return KW_STATEBLOCK; }
stateblock_state {return KW_STATEBLOCK_STATE; }
static {return KW_STATIC; }
string {return KW_STRING; }
struct {return KW_STRUCT; }
switch {return KW_SWITCH; }
tbuffer {return KW_TBUFFER; }
technique {return KW_TECHNIQUE; }
technique10 {return KW_TECHNIQUE10; }
texture {return KW_TEXTURE; }
texture1D {return KW_TEXTURE1D; }
Texture1D {return KW_TEXTURE1D; }
Texture1DArray {return KW_TEXTURE1DARRAY; }
texture2D {return KW_TEXTURE2D; }
Texture2D {return KW_TEXTURE2D; }
Texture2DArray {return KW_TEXTURE2DARRAY; }
Texture2DMS {return KW_TEXTURE2DMS; }
Texture2DMSArray {return KW_TEXTURE2DMSARRAY; }
texture3D {return KW_TEXTURE3D; }
Texture3D {return KW_TEXTURE3D; }
textureCUBE {return KW_TEXTURECUBE; }
TextureCube {return KW_TEXTURECUBE; }
TextureCubeArray {return KW_TEXTURECUBEARRAY; }
true {return KW_TRUE; }
typedef {return KW_TYPEDEF; }
uniform {return KW_UNIFORM; }
vector {return KW_VECTOR; }
VertexShader {return KW_VERTEXSHADER; }
void {return KW_VOID; }
volatile {return KW_VOLATILE; }
while {return KW_WHILE; }
\+\+ {return OP_INC; }
\-\- {return OP_DEC; }
&& {return OP_AND; }
\|\| {return OP_OR; }
== {return OP_EQ; }
\<\< {return OP_LEFTSHIFT; }
\<\<= {return OP_LEFTSHIFTASSIGN; }
\>\> {return OP_RIGHTSHIFT; }
\>\>= {return OP_RIGHTSHIFTASSIGN; }
\.\.\. {return OP_ELLIPSIS; }
\<= {return OP_LE; }
\>= {return OP_GE; }
!= {return OP_NE; }
\+= {return OP_ADDASSIGN; }
\-= {return OP_SUBASSIGN; }
\*= {return OP_MULASSIGN; }
\/= {return OP_DIVASSIGN; }
%= {return OP_MODASSIGN; }
&= {return OP_ANDASSIGN; }
\|= {return OP_ORASSIGN; }
^= {return OP_XORASSIGN; }
## {return OP_UNKNOWN1; }
#@ {return OP_UNKNOWN2; }
:: {return OP_UNKNOWN3; }
\-\> {return OP_UNKNOWN4; }
column_major {return KW_COLUMN_MAJOR; }
row_major {return KW_ROW_MAJOR; }
{IDENTIFIER} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
yylval->name = hlsl_strdup(ctx, yytext);
if (hlsl_get_var(ctx->cur_scope, yytext) || hlsl_get_function(ctx, yytext))
return VAR_IDENTIFIER;
else if (hlsl_get_type(ctx->cur_scope, yytext, true))
return TYPE_IDENTIFIER;
else
return NEW_IDENTIFIER;
}
[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[h|H|f|F]? {
yylval->floatval = atof(yytext);
return C_FLOAT;
}
[0-9]+\.([eE][+-]?[0-9]+)?[h|H|f|F]? {
yylval->floatval = atof(yytext);
return C_FLOAT;
}
[0-9]+[eE][+-]?[0-9]+[h|H|f|F]? {
yylval->floatval = atof(yytext);
return C_FLOAT;
}
0x[0-9a-fA-F]+ {
sscanf(yytext, "0x%x", &yylval->intval);
return C_INTEGER;
}
0[0-7]+ {
sscanf(yytext, "0%o", &yylval->intval);
return C_INTEGER;
}
[0-9]+ {
yylval->intval = (atoi(yytext));
return C_INTEGER;
}
{DOUBLESLASHCOMMENT} {}
{WS}+ {}
{NEWLINE} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
++ctx->location.line;
ctx->location.column = 1;
}
^# {
BEGIN(pp);
}
<pp>pragma{WS}+ {
BEGIN(pp_pragma);
}
<pp_pragma>pack_matrix{WS}*\({WS}*row_major{WS}*\) {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
TRACE("#pragma setting row_major mode.\n");
ctx->matrix_majority = HLSL_ROW_MAJOR;
BEGIN(pp_ignore);
}
<pp_pragma>pack_matrix{WS}*\({WS}*column_major{WS}*\) {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
TRACE("#pragma setting column_major mode.\n");
ctx->matrix_majority = HLSL_COLUMN_MAJOR;
BEGIN(pp_ignore);
}
<pp_pragma>{NEWLINE} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
FIXME("Unsupported preprocessor #pragma directive at line %u.\n", ctx->location.line);
BEGIN(INITIAL);
}
<pp_pragma>{ANY} {}
<pp>[0-9]+ {
BEGIN(pp_line);
yylval->intval = (atoi(yytext));
return PRE_LINE;
}
<pp_line>{STRING} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
char *string = hlsl_strdup(ctx, yytext + 1);
BEGIN(pp_ignore);
string[strlen(string) - 1] = 0;
yylval->name = string;
return STRING;
}
<pp_line>{WS}+ {}
<pp_line>{NEWLINE} {
FIXME("Malformed preprocessor line directive?\n");
BEGIN(INITIAL);
}
<pp_ignore>{NEWLINE} {
BEGIN(INITIAL);
}
<pp_ignore>{ANY} {}
<pp>{NEWLINE} {
FIXME("Unexpected preprocessor directive.\n");
BEGIN(INITIAL);
}
<pp>{ANY} {}
{ANY} {
return yytext[0];
}
%%
static void update_location(struct hlsl_ctx *ctx, YYLTYPE *lloc)
{
*lloc = ctx->location;
ctx->location.column += yyget_leng(ctx->scanner);
}
int hlsl_lexer_compile(struct hlsl_ctx *ctx, const struct vkd3d_shader_code *hlsl)
{
YY_BUFFER_STATE buffer;
int ret;
yylex_init_extra(ctx, &ctx->scanner);
buffer = yy_scan_bytes(hlsl->code, hlsl->size, ctx->scanner);
yy_switch_to_buffer(buffer, ctx->scanner);
ret = hlsl_yyparse(ctx->scanner, ctx);
yy_delete_buffer(buffer, ctx->scanner);
yylex_destroy(ctx->scanner);
return ret;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,285 @@
/*
* HLSL constant value operations for constant folding
*
* Copyright 2022 Francisco Casas 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 "hlsl.h"
static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src)
{
unsigned int k;
uint32_t u;
int32_t i;
double d;
float f;
bool b;
if (dst->node.data_type->dimx != src->node.data_type->dimx
|| dst->node.data_type->dimy != src->node.data_type->dimy)
{
FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
for (k = 0; k < 4; ++k)
{
switch (src->node.data_type->base_type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
u = src->value[k].f;
i = src->value[k].f;
f = src->value[k].f;
d = src->value[k].f;
b = src->value[k].f;
break;
case HLSL_TYPE_DOUBLE:
u = src->value[k].d;
i = src->value[k].d;
f = src->value[k].d;
d = src->value[k].d;
b = src->value[k].d;
break;
case HLSL_TYPE_INT:
u = src->value[k].i;
i = src->value[k].i;
f = src->value[k].i;
d = src->value[k].i;
b = src->value[k].i;
break;
case HLSL_TYPE_UINT:
u = src->value[k].u;
i = src->value[k].u;
f = src->value[k].u;
d = src->value[k].u;
b = src->value[k].u;
break;
case HLSL_TYPE_BOOL:
u = src->value[k].b;
i = src->value[k].b;
f = src->value[k].b;
d = src->value[k].b;
b = src->value[k].b;
break;
default:
FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
switch (dst->node.data_type->base_type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
dst->value[k].f = f;
break;
case HLSL_TYPE_DOUBLE:
dst->value[k].d = d;
break;
case HLSL_TYPE_INT:
dst->value[k].i = i;
break;
case HLSL_TYPE_UINT:
dst->value[k].u = u;
break;
case HLSL_TYPE_BOOL:
dst->value[k].b = b;
break;
default:
FIXME("Cast from %s to %s.\n", debug_hlsl_type(ctx, src->node.data_type),
debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
}
return true;
}
static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst->node.data_type->base_type;
unsigned int k;
assert(type == src->node.data_type->base_type);
for (k = 0; k < 4; ++k)
{
switch (type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
dst->value[k].f = -src->value[k].f;
break;
case HLSL_TYPE_DOUBLE:
dst->value[k].d = -src->value[k].d;
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
dst->value[k].u = -src->value[k].u;
break;
default:
FIXME("Fold negation for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
}
return true;
}
static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, struct hlsl_ir_constant *src1,
struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst->node.data_type->base_type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
for (k = 0; k < 4; ++k)
{
switch (type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
dst->value[k].f = src1->value[k].f + src2->value[k].f;
break;
case HLSL_TYPE_DOUBLE:
dst->value[k].d = src1->value[k].d + src2->value[k].d;
break;
/* Handling HLSL_TYPE_INT through the unsigned field to avoid
* undefined behavior with signed integers in C. */
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
dst->value[k].u = src1->value[k].u + src2->value[k].u;
break;
default:
FIXME("Fold addition for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
}
return true;
}
static bool fold_mul(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst,
struct hlsl_ir_constant *src1, struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst->node.data_type->base_type;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
for (int k = 0; k < 4; ++k)
{
switch (type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
dst->value[k].f = src1->value[k].f * src2->value[k].f;
break;
case HLSL_TYPE_DOUBLE:
dst->value[k].d = src1->value[k].d * src2->value[k].d;
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
dst->value[k].u = src1->value[k].u * src2->value[k].u;
break;
default:
FIXME("Fold multiplication for type %s.\n", debug_hlsl_type(ctx, dst->node.data_type));
return false;
}
}
return true;
}
bool hlsl_fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_ir_constant *arg1, *arg2 = NULL, *res;
struct hlsl_ir_expr *expr;
unsigned int i;
bool success;
if (instr->type != HLSL_IR_EXPR)
return false;
expr = hlsl_ir_expr(instr);
for (i = 0; i < ARRAY_SIZE(expr->operands); ++i)
{
if (expr->operands[i].node && expr->operands[i].node->type != HLSL_IR_CONSTANT)
return false;
}
arg1 = hlsl_ir_constant(expr->operands[0].node);
if (expr->operands[1].node)
arg2 = hlsl_ir_constant(expr->operands[1].node);
if (!(res = hlsl_alloc(ctx, sizeof(*res))))
return false;
init_node(&res->node, HLSL_IR_CONSTANT, instr->data_type, instr->loc);
switch (expr->op)
{
case HLSL_OP1_CAST:
success = fold_cast(ctx, res, arg1);
break;
case HLSL_OP1_NEG:
success = fold_neg(ctx, res, arg1);
break;
case HLSL_OP2_ADD:
success = fold_add(ctx, res, arg1, arg2);
break;
case HLSL_OP2_MUL:
success = fold_mul(ctx, res, arg1, arg2);
break;
default:
FIXME("Fold \"%s\" expression.\n", debug_hlsl_expr_op(expr->op));
success = false;
break;
}
if (success)
{
list_add_before(&expr->node.entry, &res->node.entry);
hlsl_replace_node(&expr->node, &res->node);
}
else
{
vkd3d_free(res);
}
return success;
}

View File

@ -0,0 +1,849 @@
/*
* HLSL code generation for DXBC shader models 1-3
*
* Copyright 2019-2020 Zebediah Figura 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 "hlsl.h"
#include <stdio.h>
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg)
{
unsigned int i;
static const struct
{
const char *semantic;
bool output;
enum vkd3d_shader_type shader_type;
unsigned int major_version;
D3DSHADER_PARAM_REGISTER_TYPE type;
DWORD offset;
}
register_table[] =
{
{"color", true, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_COLOROUT},
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_DEPTHOUT},
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_DEPTHOUT},
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_COLOROUT},
{"color", false, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_INPUT},
{"texcoord", false, VKD3D_SHADER_TYPE_PIXEL, 2, D3DSPR_TEXTURE},
{"color", true, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_COLOROUT},
{"depth", true, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_DEPTHOUT},
{"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_DEPTHOUT},
{"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_COLOROUT},
{"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_MISCTYPE, D3DSMO_POSITION},
{"vface", false, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_MISCTYPE, D3DSMO_FACE},
{"vpos", false, VKD3D_SHADER_TYPE_PIXEL, 3, D3DSPR_MISCTYPE, D3DSMO_POSITION},
{"color", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_ATTROUT},
{"fog", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_RASTOUT, D3DSRO_FOG},
{"position", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_RASTOUT, D3DSRO_POSITION},
{"psize", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_RASTOUT, D3DSRO_POINT_SIZE},
{"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_RASTOUT, D3DSRO_POSITION},
{"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 1, D3DSPR_TEXCRDOUT},
{"color", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_ATTROUT},
{"fog", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_RASTOUT, D3DSRO_FOG},
{"position", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_RASTOUT, D3DSRO_POSITION},
{"psize", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_RASTOUT, D3DSRO_POINT_SIZE},
{"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_RASTOUT, D3DSRO_POSITION},
{"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 2, D3DSPR_TEXCRDOUT},
};
for (i = 0; i < ARRAY_SIZE(register_table); ++i)
{
if (!ascii_strcasecmp(semantic->name, register_table[i].semantic)
&& output == register_table[i].output
&& ctx->profile->type == register_table[i].shader_type
&& ctx->profile->major_version == register_table[i].major_version)
{
*type = register_table[i].type;
if (register_table[i].type == D3DSPR_MISCTYPE || register_table[i].type == D3DSPR_RASTOUT)
*reg = register_table[i].offset;
else
*reg = semantic->index;
return true;
}
}
return false;
}
bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx)
{
static const struct
{
const char *name;
D3DDECLUSAGE usage;
}
semantics[] =
{
{"binormal", D3DDECLUSAGE_BINORMAL},
{"blendindices", D3DDECLUSAGE_BLENDINDICES},
{"blendweight", D3DDECLUSAGE_BLENDWEIGHT},
{"color", D3DDECLUSAGE_COLOR},
{"depth", D3DDECLUSAGE_DEPTH},
{"fog", D3DDECLUSAGE_FOG},
{"normal", D3DDECLUSAGE_NORMAL},
{"position", D3DDECLUSAGE_POSITION},
{"positiont", D3DDECLUSAGE_POSITIONT},
{"psize", D3DDECLUSAGE_PSIZE},
{"sample", D3DDECLUSAGE_SAMPLE},
{"sv_depth", D3DDECLUSAGE_DEPTH},
{"sv_position", D3DDECLUSAGE_POSITION},
{"sv_target", D3DDECLUSAGE_COLOR},
{"tangent", D3DDECLUSAGE_TANGENT},
{"tessfactor", D3DDECLUSAGE_TESSFACTOR},
{"texcoord", D3DDECLUSAGE_TEXCOORD},
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(semantics); ++i)
{
if (!ascii_strcasecmp(semantic->name, semantics[i].name))
{
*usage = semantics[i].usage;
*usage_idx = semantic->index;
return true;
}
}
return false;
}
static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, unsigned int minor)
{
if (type == VKD3D_SHADER_TYPE_VERTEX)
return D3DVS_VERSION(major, minor);
else
return D3DPS_VERSION(major, minor);
}
static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type)
{
switch (type->type)
{
case HLSL_CLASS_ARRAY:
return sm1_class(type->e.array.type);
case HLSL_CLASS_MATRIX:
assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
return D3DXPC_MATRIX_COLUMNS;
else
return D3DXPC_MATRIX_ROWS;
case HLSL_CLASS_OBJECT:
return D3DXPC_OBJECT;
case HLSL_CLASS_SCALAR:
return D3DXPC_SCALAR;
case HLSL_CLASS_STRUCT:
return D3DXPC_STRUCT;
case HLSL_CLASS_VECTOR:
return D3DXPC_VECTOR;
default:
ERR("Invalid class %#x.\n", type->type);
assert(0);
return 0;
}
}
static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type)
{
switch (type->base_type)
{
case HLSL_TYPE_BOOL:
return D3DXPT_BOOL;
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
return D3DXPT_FLOAT;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
return D3DXPT_INT;
case HLSL_TYPE_PIXELSHADER:
return D3DXPT_PIXELSHADER;
case HLSL_TYPE_SAMPLER:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
return D3DXPT_SAMPLER1D;
case HLSL_SAMPLER_DIM_2D:
return D3DXPT_SAMPLER2D;
case HLSL_SAMPLER_DIM_3D:
return D3DXPT_SAMPLER3D;
case HLSL_SAMPLER_DIM_CUBE:
return D3DXPT_SAMPLERCUBE;
case HLSL_SAMPLER_DIM_GENERIC:
return D3DXPT_SAMPLER;
default:
ERR("Invalid dimension %#x.\n", type->sampler_dim);
}
break;
case HLSL_TYPE_STRING:
return D3DXPT_STRING;
case HLSL_TYPE_TEXTURE:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
return D3DXPT_TEXTURE1D;
case HLSL_SAMPLER_DIM_2D:
return D3DXPT_TEXTURE2D;
case HLSL_SAMPLER_DIM_3D:
return D3DXPT_TEXTURE3D;
case HLSL_SAMPLER_DIM_CUBE:
return D3DXPT_TEXTURECUBE;
case HLSL_SAMPLER_DIM_GENERIC:
return D3DXPT_TEXTURE;
default:
ERR("Invalid dimension %#x.\n", type->sampler_dim);
}
break;
case HLSL_TYPE_VERTEXSHADER:
return D3DXPT_VERTEXSHADER;
case HLSL_TYPE_VOID:
return D3DXPT_VOID;
default:
assert(0);
}
assert(0);
return 0;
}
static const struct hlsl_type *get_array_type(const struct hlsl_type *type)
{
if (type->type == HLSL_CLASS_ARRAY)
return get_array_type(type->e.array.type);
return type;
}
static unsigned int get_array_size(const struct hlsl_type *type)
{
if (type->type == HLSL_CLASS_ARRAY)
return get_array_size(type->e.array.type) * type->e.array.elements_count;
return 1;
}
static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start)
{
const struct hlsl_type *array_type = get_array_type(type);
unsigned int array_size = get_array_size(type);
struct hlsl_struct_field *field;
unsigned int field_count = 0;
size_t fields_offset = 0;
if (type->bytecode_offset)
return;
if (array_type->type == HLSL_CLASS_STRUCT)
{
LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry)
{
field->name_bytecode_offset = put_string(buffer, field->name);
write_sm1_type(buffer, field->type, ctab_start);
}
fields_offset = bytecode_get_size(buffer) - ctab_start;
LIST_FOR_EACH_ENTRY(field, array_type->e.elements, struct hlsl_struct_field, entry)
{
put_u32(buffer, field->name_bytecode_offset - ctab_start);
put_u32(buffer, field->type->bytecode_offset - ctab_start);
++field_count;
}
}
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm1_class(type), sm1_base_type(type)));
put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx));
put_u32(buffer, vkd3d_make_u32(array_size, field_count));
put_u32(buffer, fields_offset);
}
static void sm1_sort_extern(struct list *sorted, struct hlsl_ir_var *to_sort)
{
struct hlsl_ir_var *var;
list_remove(&to_sort->extern_entry);
LIST_FOR_EACH_ENTRY(var, sorted, struct hlsl_ir_var, extern_entry)
{
if (strcmp(to_sort->name, var->name) < 0)
{
list_add_before(&var->extern_entry, &to_sort->extern_entry);
return;
}
}
list_add_tail(sorted, &to_sort->extern_entry);
}
static void sm1_sort_externs(struct hlsl_ctx *ctx)
{
struct list sorted = LIST_INIT(sorted);
struct hlsl_ir_var *var, *next;
LIST_FOR_EACH_ENTRY_SAFE(var, next, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
sm1_sort_extern(&sorted, var);
list_move_tail(&ctx->extern_vars, &sorted);
}
static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
struct hlsl_ir_function_decl *entry_func)
{
size_t ctab_offset, ctab_start, ctab_end, vars_start, size_offset, creator_offset, offset;
unsigned int uniform_count = 0;
struct hlsl_ir_var *var;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
{
++uniform_count;
if (var->is_param && var->is_uniform)
{
struct vkd3d_string_buffer *name;
if (!(name = hlsl_get_string_buffer(ctx)))
{
buffer->status = VKD3D_ERROR_OUT_OF_MEMORY;
return;
}
vkd3d_string_buffer_printf(name, "$%s", var->name);
vkd3d_free((char *)var->name);
var->name = hlsl_strdup(ctx, name->buffer);
hlsl_release_string_buffer(ctx, name);
}
}
}
sm1_sort_externs(ctx);
size_offset = put_u32(buffer, 0);
ctab_offset = put_u32(buffer, VKD3D_MAKE_TAG('C','T','A','B'));
ctab_start = put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE));
creator_offset = put_u32(buffer, 0);
put_u32(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version));
put_u32(buffer, uniform_count);
put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */
put_u32(buffer, 0); /* FIXME: flags */
put_u32(buffer, 0); /* FIXME: target string */
vars_start = bytecode_get_size(buffer);
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
{
put_u32(buffer, 0); /* name */
if (var->data_type->type == HLSL_CLASS_OBJECT
&& (var->data_type->base_type == HLSL_TYPE_SAMPLER
|| var->data_type->base_type == HLSL_TYPE_TEXTURE))
{
put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->reg.id));
put_u32(buffer, 1);
}
else
{
put_u32(buffer, vkd3d_make_u32(D3DXRS_FLOAT4, var->reg.id));
put_u32(buffer, var->data_type->reg_size / 4);
}
put_u32(buffer, 0); /* type */
put_u32(buffer, 0); /* FIXME: default value */
}
}
uniform_count = 0;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!var->semantic.name && var->reg.allocated)
{
size_t var_offset = vars_start + (uniform_count * 5 * sizeof(uint32_t));
size_t name_offset;
name_offset = put_string(buffer, var->name);
set_u32(buffer, var_offset, name_offset - ctab_start);
write_sm1_type(buffer, var->data_type, ctab_start);
set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start);
++uniform_count;
}
}
offset = put_string(buffer, vkd3d_shader_get_version(NULL, NULL));
set_u32(buffer, creator_offset, offset - ctab_start);
ctab_end = bytecode_get_size(buffer);
set_u32(buffer, size_offset, vkd3d_make_u32(D3DSIO_COMMENT, (ctab_end - ctab_offset) / sizeof(uint32_t)));
}
static uint32_t sm1_encode_register_type(D3DSHADER_PARAM_REGISTER_TYPE type)
{
return ((type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK)
| ((type << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2);
}
struct sm1_instruction
{
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode;
struct sm1_dst_register
{
D3DSHADER_PARAM_REGISTER_TYPE type;
D3DSHADER_PARAM_DSTMOD_TYPE mod;
unsigned int writemask;
uint32_t reg;
} dst;
struct sm1_src_register
{
D3DSHADER_PARAM_REGISTER_TYPE type;
D3DSHADER_PARAM_SRCMOD_TYPE mod;
unsigned int swizzle;
uint32_t reg;
} srcs[2];
unsigned int src_count;
unsigned int has_dst;
};
static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const struct sm1_dst_register *reg)
{
assert(reg->writemask);
put_u32(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (reg->writemask << 16) | reg->reg);
}
static void write_sm1_src_register(struct vkd3d_bytecode_buffer *buffer,
const struct sm1_src_register *reg, unsigned int dst_writemask)
{
unsigned int swizzle = hlsl_map_swizzle(reg->swizzle, dst_writemask);
put_u32(buffer, (1u << 31) | sm1_encode_register_type(reg->type) | reg->mod | (swizzle << 16) | reg->reg);
}
static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct sm1_instruction *instr)
{
uint32_t token = instr->opcode;
unsigned int i;
if (ctx->profile->major_version > 1)
token |= (instr->has_dst + instr->src_count) << D3DSI_INSTLENGTH_SHIFT;
put_u32(buffer, token);
if (instr->has_dst)
write_sm1_dst_register(buffer, &instr->dst);
for (i = 0; i < instr->src_count; ++i)
write_sm1_src_register(buffer, &instr->srcs[i], instr->dst.writemask);
};
static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src1, const struct hlsl_reg *src2)
{
const struct sm1_instruction instr =
{
.opcode = opcode,
.dst.type = D3DSPR_TEMP,
.dst.writemask = dst->writemask,
.dst.reg = dst->id,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(src1->writemask),
.srcs[0].reg = src1->id,
.srcs[1].type = D3DSPR_TEMP,
.srcs[1].swizzle = hlsl_swizzle_from_writemask(src2->writemask),
.srcs[1].reg = src2->id,
.src_count = 2,
};
write_sm1_instruction(ctx, buffer, &instr);
}
static void write_sm1_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src, D3DSHADER_PARAM_SRCMOD_TYPE src_mod)
{
const struct sm1_instruction instr =
{
.opcode = opcode,
.dst.type = D3DSPR_TEMP,
.dst.writemask = dst->writemask,
.dst.reg = dst->id,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(src->writemask),
.srcs[0].reg = src->id,
.srcs[0].mod = src_mod,
.src_count = 1,
};
write_sm1_instruction(ctx, buffer, &instr);
}
static void write_sm1_constant_defs(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer)
{
unsigned int i, x;
for (i = 0; i < ctx->constant_defs.count; ++i)
{
uint32_t token = D3DSIO_DEF;
const struct sm1_dst_register reg =
{
.type = D3DSPR_CONST,
.writemask = VKD3DSP_WRITEMASK_ALL,
.reg = i,
};
if (ctx->profile->major_version > 1)
token |= 5 << D3DSI_INSTLENGTH_SHIFT;
put_u32(buffer, token);
write_sm1_dst_register(buffer, &reg);
for (x = 0; x < 4; ++x)
put_f32(buffer, ctx->constant_defs.values[i].f[x]);
}
}
static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_var *var, bool output)
{
struct sm1_dst_register reg = {0};
uint32_t token, usage_idx;
D3DDECLUSAGE usage;
bool ret;
if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &reg.type, &reg.reg))
{
usage = 0;
usage_idx = 0;
}
else
{
ret = hlsl_sm1_usage_from_semantic(&var->semantic, &usage, &usage_idx);
assert(ret);
reg.type = output ? D3DSPR_OUTPUT : D3DSPR_INPUT;
reg.reg = var->reg.id;
}
token = D3DSIO_DCL;
if (ctx->profile->major_version > 1)
token |= 2 << D3DSI_INSTLENGTH_SHIFT;
put_u32(buffer, token);
token = (1u << 31);
token |= usage << D3DSP_DCL_USAGE_SHIFT;
token |= usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT;
put_u32(buffer, token);
reg.writemask = (1 << var->data_type->dimx) - 1;
write_sm1_dst_register(buffer, &reg);
}
static void write_sm1_semantic_dcls(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer)
{
bool write_in = false, write_out = false;
struct hlsl_ir_var *var;
if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
write_in = true;
else if (ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX && ctx->profile->major_version == 3)
write_in = write_out = true;
else if (ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX && ctx->profile->major_version < 3)
write_in = true;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (write_in && var->is_input_semantic)
write_sm1_semantic_dcl(ctx, buffer, var, false);
if (write_out && var->is_output_semantic)
write_sm1_semantic_dcl(ctx, buffer, var, true);
}
}
static void write_sm1_constant(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_constant *constant = hlsl_ir_constant(instr);
struct sm1_instruction sm1_instr =
{
.opcode = D3DSIO_MOV,
.dst.type = D3DSPR_TEMP,
.dst.reg = instr->reg.id,
.dst.writemask = instr->reg.writemask,
.has_dst = 1,
.srcs[0].type = D3DSPR_CONST,
.srcs[0].reg = constant->reg.id,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(constant->reg.writemask),
.src_count = 1,
};
assert(instr->reg.allocated);
assert(constant->reg.allocated);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
struct hlsl_ir_node *arg1 = expr->operands[0].node;
struct hlsl_ir_node *arg2 = expr->operands[1].node;
unsigned int i;
assert(instr->reg.allocated);
if (instr->data_type->base_type != HLSL_TYPE_FLOAT)
{
/* These need to be lowered. */
hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression.");
return;
}
switch (expr->op)
{
case HLSL_OP1_NEG:
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG);
break;
case HLSL_OP1_RCP:
for (i = 0; i < instr->data_type->dimx; ++i)
{
struct hlsl_reg src = arg1->reg, dst = instr->reg;
src.writemask = hlsl_combine_writemasks(src.writemask, 1u << i);
dst.writemask = hlsl_combine_writemasks(dst.writemask, 1u << i);
write_sm1_unary_op(ctx, buffer, D3DSIO_RCP, &dst, &src, 0);
}
break;
case HLSL_OP2_ADD:
write_sm1_binary_op(ctx, buffer, D3DSIO_ADD, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP2_MAX:
write_sm1_binary_op(ctx, buffer, D3DSIO_MAX, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP2_MIN:
write_sm1_binary_op(ctx, buffer, D3DSIO_MIN, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP2_MUL:
write_sm1_binary_op(ctx, buffer, D3DSIO_MUL, &instr->reg, &arg1->reg, &arg2->reg);
break;
default:
hlsl_fixme(ctx, &instr->loc, "SM1 \"%s\" expression.", debug_hlsl_expr_op(expr->op));
break;
}
}
static void write_sm1_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_load *load = hlsl_ir_load(instr);
const struct hlsl_reg reg = hlsl_reg_from_deref(ctx, &load->src, instr->data_type);
struct sm1_instruction sm1_instr =
{
.opcode = D3DSIO_MOV,
.dst.type = D3DSPR_TEMP,
.dst.reg = instr->reg.id,
.dst.writemask = instr->reg.writemask,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].reg = reg.id,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(reg.writemask),
.src_count = 1,
};
assert(instr->reg.allocated);
if (load->src.var->is_uniform)
{
assert(reg.allocated);
sm1_instr.srcs[0].type = D3DSPR_CONST;
}
else if (load->src.var->is_input_semantic)
{
if (!hlsl_sm1_register_from_semantic(ctx, &load->src.var->semantic,
false, &sm1_instr.srcs[0].type, &sm1_instr.srcs[0].reg))
{
assert(reg.allocated);
sm1_instr.srcs[0].type = D3DSPR_INPUT;
sm1_instr.srcs[0].reg = reg.id;
}
else
sm1_instr.srcs[0].swizzle = hlsl_swizzle_from_writemask((1 << load->src.var->data_type->dimx) - 1);
}
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
static void write_sm1_store(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_store *store = hlsl_ir_store(instr);
const struct hlsl_ir_node *rhs = store->rhs.node;
const struct hlsl_reg reg = hlsl_reg_from_deref(ctx, &store->lhs, rhs->data_type);
struct sm1_instruction sm1_instr =
{
.opcode = D3DSIO_MOV,
.dst.type = D3DSPR_TEMP,
.dst.reg = reg.id,
.dst.writemask = hlsl_combine_writemasks(reg.writemask, store->writemask),
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].reg = rhs->reg.id,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(rhs->reg.writemask),
.src_count = 1,
};
if (store->lhs.var->data_type->type == HLSL_CLASS_MATRIX)
{
FIXME("Matrix writemasks need to be lowered.\n");
return;
}
if (store->lhs.var->is_output_semantic)
{
if (!hlsl_sm1_register_from_semantic(ctx, &store->lhs.var->semantic,
true, &sm1_instr.dst.type, &sm1_instr.dst.reg))
{
assert(reg.allocated);
sm1_instr.dst.type = D3DSPR_OUTPUT;
sm1_instr.dst.reg = reg.id;
}
else
sm1_instr.dst.writemask = (1u << store->lhs.var->data_type->dimx) - 1;
}
else
assert(reg.allocated);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr);
const struct hlsl_ir_node *val = swizzle->val.node;
struct sm1_instruction sm1_instr =
{
.opcode = D3DSIO_MOV,
.dst.type = D3DSPR_TEMP,
.dst.reg = instr->reg.id,
.dst.writemask = instr->reg.writemask,
.has_dst = 1,
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].reg = val->reg.id,
.srcs[0].swizzle = hlsl_combine_swizzles(hlsl_swizzle_from_writemask(val->reg.writemask),
swizzle->swizzle, instr->data_type->dimx),
.src_count = 1,
};
assert(instr->reg.allocated);
assert(val->reg.allocated);
write_sm1_instruction(ctx, buffer, &sm1_instr);
}
static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_function_decl *entry_func)
{
const struct hlsl_ir_node *instr;
LIST_FOR_EACH_ENTRY(instr, &entry_func->body.instrs, struct hlsl_ir_node, entry)
{
if (instr->data_type)
{
if (instr->data_type->type == HLSL_CLASS_MATRIX)
{
/* These need to be lowered. */
hlsl_fixme(ctx, &instr->loc, "SM1 matrix expression.");
continue;
}
else if (instr->data_type->type == HLSL_CLASS_OBJECT)
{
hlsl_fixme(ctx, &instr->loc, "Object copy.\n");
break;
}
assert(instr->data_type->type == HLSL_CLASS_SCALAR || instr->data_type->type == HLSL_CLASS_VECTOR);
}
switch (instr->type)
{
case HLSL_IR_CONSTANT:
write_sm1_constant(ctx, buffer, instr);
break;
case HLSL_IR_EXPR:
write_sm1_expr(ctx, buffer, instr);
break;
case HLSL_IR_LOAD:
write_sm1_load(ctx, buffer, instr);
break;
case HLSL_IR_STORE:
write_sm1_store(ctx, buffer, instr);
break;
case HLSL_IR_SWIZZLE:
write_sm1_swizzle(ctx, buffer, instr);
break;
default:
FIXME("Unhandled instruction type %s.\n", hlsl_node_type_to_string(instr->type));
}
}
}
int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out)
{
struct vkd3d_bytecode_buffer buffer = {0};
int ret;
put_u32(&buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version));
write_sm1_uniforms(ctx, &buffer, entry_func);
write_sm1_constant_defs(ctx, &buffer);
write_sm1_semantic_dcls(ctx, &buffer);
write_sm1_instructions(ctx, &buffer, entry_func);
put_u32(&buffer, D3DSIO_END);
if (!(ret = buffer.status))
{
out->code = buffer.data;
out->size = buffer.size;
}
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
/*
* HLSL preprocessor
*
* Copyright 2020 Zebediah Figura 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_SHADER_PREPROC_H
#define __VKD3D_SHADER_PREPROC_H
#include "vkd3d_shader_private.h"
#include "wine/rbtree.h"
struct preproc_if_state
{
/* Are we currently in a "true" block? */
bool current_true;
/* Have we seen a "true" block in this #if..#endif yet? */
bool seen_true;
/* Have we seen an #else yet? */
bool seen_else;
};
struct preproc_buffer
{
void *lexer_buffer;
struct vkd3d_shader_location location;
};
struct preproc_file
{
struct preproc_buffer buffer;
struct vkd3d_shader_code code;
char *filename;
struct preproc_if_state *if_stack;
size_t if_count, if_stack_size;
};
struct preproc_text
{
struct vkd3d_string_buffer text;
struct vkd3d_shader_location location;
};
struct preproc_expansion
{
struct preproc_buffer buffer;
const struct preproc_text *text;
/* Back-pointer to the macro, if this expansion a macro body. This is
* necessary so that argument tokens can be correctly replaced. */
struct preproc_macro *macro;
};
struct preproc_macro
{
struct rb_entry entry;
char *name;
char **arg_names;
size_t arg_count;
struct preproc_text *arg_values;
struct preproc_text body;
};
struct preproc_ctx
{
const struct vkd3d_shader_preprocess_info *preprocess_info;
void *scanner;
struct vkd3d_shader_message_context *message_context;
struct vkd3d_string_buffer buffer;
struct preproc_file *file_stack;
size_t file_count, file_stack_size;
struct preproc_expansion *expansion_stack;
size_t expansion_count, expansion_stack_size;
struct rb_tree macros;
/* It's possible to parse as many as two function-like macros at once: one
* in the main text, and another inside of #if directives. E.g.
*
* func1(
* #if func2(...)
* #endif
* )
*
* It's not possible to parse more than two, however. In the case of nested
* calls like "func1(func2(...))", we store everything inside the outer
* parentheses as unparsed text, and then parse it once the argument is
* actually invoked.
*/
struct preproc_func_state
{
struct preproc_macro *macro;
size_t arg_count;
enum
{
STATE_NONE = 0,
STATE_IDENTIFIER,
STATE_ARGS,
} state;
unsigned int paren_depth;
} text_func, directive_func;
int current_directive;
int lookahead_token;
bool last_was_newline;
bool last_was_eof;
bool last_was_defined;
bool error;
};
bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc, char *name, char **arg_names,
size_t arg_count, const struct vkd3d_shader_location *body_loc, struct vkd3d_string_buffer *body);
void preproc_close_include(struct preproc_ctx *ctx, const struct vkd3d_shader_code *code);
struct preproc_macro *preproc_find_macro(struct preproc_ctx *ctx, const char *name);
void preproc_free_macro(struct preproc_macro *macro);
bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct vkd3d_shader_code *code);
void preproc_warning(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5);
static inline struct preproc_file *preproc_get_top_file(struct preproc_ctx *ctx)
{
assert(ctx->file_count);
return &ctx->file_stack[ctx->file_count - 1];
}
#endif

View File

@ -0,0 +1,823 @@
/*
* HLSL preprocessor
*
* Copyright 2020 Zebediah Figura 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 "preproc.h"
#include "preproc.tab.h"
#undef ERROR /* defined in wingdi.h */
#define YYSTYPE PREPROC_YYSTYPE
#define YYLTYPE PREPROC_YYLTYPE
#define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner)
static void update_location(struct preproc_ctx *ctx);
#define YY_USER_ACTION update_location(yyget_extra(yyscanner));
%}
%option 8bit
%option bison-bridge
%option bison-locations
%option extra-type="struct preproc_ctx *"
%option never-interactive
%option noinput
%option nounput
%option noyy_top_state
%option noyywrap
%option prefix="preproc_yy"
%option reentrant
%option stack
/* Because these can both be terminated by EOF, we need states for them. */
%s C_COMMENT
%s CXX_COMMENT
%s ERROR
%s INCLUDE
%s LINE
NEWLINE \r?\n
WS [ \t]
IDENTIFIER [A-Za-z_][A-Za-z0-9_]*
INT_SUFFIX [uUlL]{0,2}
%%
<INITIAL>"//" {yy_push_state(CXX_COMMENT, yyscanner);}
<INITIAL>"/*" {yy_push_state(C_COMMENT, yyscanner);}
<CXX_COMMENT>\\{NEWLINE} {}
<CXX_COMMENT>\n {
yy_pop_state(yyscanner);
BEGIN(INITIAL);
return T_NEWLINE;
}
<C_COMMENT>"*/" {yy_pop_state(yyscanner);}
<C_COMMENT,CXX_COMMENT><<EOF>> {yy_pop_state(yyscanner);}
<C_COMMENT,CXX_COMMENT>. {}
<ERROR>(\\{NEWLINE}|[^\n])* {return T_STRING;}
<INITIAL>defined/\( {return T_DEFINED;}
<INITIAL>defined {return T_DEFINED;}
<INITIAL>{IDENTIFIER}/\( {return T_IDENTIFIER_PAREN;}
<INITIAL>{IDENTIFIER} {return T_IDENTIFIER;}
<INITIAL>"<=" {return T_LE;}
<INITIAL>">=" {return T_GE;}
<INITIAL>"==" {return T_EQ;}
<INITIAL>"!=" {return T_NE;}
<INITIAL>"&&" {return T_AND;}
<INITIAL>"||" {return T_OR;}
/* We have no use for floats, but shouldn't parse them as integers. */
<INITIAL>[0-9]*\.[0-9]+([eE][+-]?[0-9]+)?[hHfF]? {return T_TEXT;}
<INITIAL>[0-9]+\.([eE][+-]?[0-9]+)?[hHfF]? {return T_TEXT;}
<INITIAL>[0-9]+([eE][+-]?[0-9]+)?[hHfF] {return T_TEXT;}
<INITIAL>[0-9]+[eE][+-]?[0-9]+ {return T_TEXT;}
<INITIAL,LINE>0[xX][0-9a-fA-f]+{INT_SUFFIX} {return T_INTEGER;}
<INITIAL,LINE>0[0-7]*{INT_SUFFIX} {return T_INTEGER;}
<INITIAL,LINE>[1-9][0-9]*{INT_SUFFIX} {return T_INTEGER;}
<INITIAL>## {return T_CONCAT;}
<INITIAL>"++" {return T_TEXT;}
<INITIAL>"--" {return T_TEXT;}
<INITIAL>"<<"=? {return T_TEXT;}
<INITIAL>">>"=? {return T_TEXT;}
<INITIAL>[-+*/%&|^]= {return T_TEXT;}
/* Native doesn't preserve these tokens when running the preprocessor on its
* own, but there's no good reason to emulate that difference yet. */
<INITIAL>[pv]s\.[123]\.[0-4x] {return T_TEXT;}
<INCLUDE,LINE>\"[^"]*\" {return T_STRING;}
<INCLUDE>\<[^>]*\> {return T_STRING;}
/* C strings (including escaped quotes). */
<INITIAL>\"([^"\\]|\\.)*\" {return T_TEXT;}
<INITIAL>#{WS}*{IDENTIFIER} {
struct preproc_ctx *ctx = yyget_extra(yyscanner);
const char *p;
if (!ctx->last_was_newline)
return T_HASHSTRING;
for (p = yytext + 1; strchr(" \t", *p); ++p)
;
if (!strcmp(p, "error"))
{
BEGIN(ERROR);
return T_ERROR;
}
if (!strcmp(p, "include"))
{
BEGIN(INCLUDE);
return T_INCLUDE;
}
if (!strcmp(p, "line"))
{
BEGIN(LINE);
return T_LINE;
}
if (!strcmp(p, "define"))
return T_DEFINE;
if (!strcmp(p, "elif"))
return T_ELIF;
if (!strcmp(p, "else"))
return T_ELSE;
if (!strcmp(p, "endif"))
return T_ENDIF;
if (!strcmp(p, "if"))
return T_IF;
if (!strcmp(p, "ifdef"))
return T_IFDEF;
if (!strcmp(p, "ifndef"))
return T_IFNDEF;
if (!strcmp(p, "pragma"))
return T_PRAGMA;
if (!strcmp(p, "undef"))
return T_UNDEF;
preproc_warning(ctx, yyget_lloc(yyscanner), VKD3D_SHADER_WARNING_PP_UNKNOWN_DIRECTIVE,
"Ignoring unknown directive \"%s\".", yytext);
return T_TEXT;
}
<INITIAL,INCLUDE,LINE>\\{NEWLINE} {}
<INITIAL,INCLUDE,ERROR,LINE>{NEWLINE} {
BEGIN(INITIAL);
return T_NEWLINE;
}
<INITIAL>{WS}+ {}
<INITIAL>[-()\[\]{},+!*/<>&|^?:] {return yytext[0];}
<INITIAL>. {return T_TEXT;}
%%
static void update_location(struct preproc_ctx *ctx)
{
struct preproc_buffer *buffer = &preproc_get_top_file(ctx)->buffer;
unsigned int i, leng = yyget_leng(ctx->scanner);
const char *text = yyget_text(ctx->scanner);
/* We want to do this here, rather than before calling yylex(), because
* some tokens are skipped by the lexer. */
*yyget_lloc(ctx->scanner) = buffer->location;
for (i = 0; i < leng; ++i)
{
++buffer->location.column;
if (text[i] == '\n')
{
buffer->location.column = 1;
++buffer->location.line;
}
}
}
static bool preproc_is_writing(struct preproc_ctx *ctx)
{
const struct preproc_file *file;
/* This can happen while checking for unterminated macro invocation. */
if (!ctx->file_count)
return true;
file = preproc_get_top_file(ctx);
if (!file->if_count)
return true;
return file->if_stack[file->if_count - 1].current_true;
}
static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx)
{
if (!ctx->expansion_count)
return NULL;
return ctx->expansion_stack[ctx->expansion_count - 1].macro;
}
/* Concatenation is not done for object-like macros, but is done for both
* function-like macro bodies and their arguments. */
static bool should_concat(struct preproc_ctx *ctx)
{
struct preproc_macro *macro;
if (!ctx->expansion_count)
return false;
macro = ctx->expansion_stack[ctx->expansion_count - 1].macro;
return !macro || macro->arg_count;
}
static void preproc_pop_buffer(struct preproc_ctx *ctx)
{
if (ctx->expansion_count)
{
struct preproc_expansion *exp = &ctx->expansion_stack[ctx->expansion_count - 1];
yy_delete_buffer(exp->buffer.lexer_buffer, ctx->scanner);
--ctx->expansion_count;
TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count);
}
else
{
struct preproc_file *file = preproc_get_top_file(ctx);
if (ctx->file_count > 1)
preproc_close_include(ctx, &file->code);
if (file->if_count)
{
const struct vkd3d_shader_location loc = {.source_name = file->filename};
preproc_warning(ctx, &loc, VKD3D_SHADER_WARNING_PP_UNTERMINATED_IF, "Unterminated #if block.");
}
vkd3d_free(file->if_stack);
vkd3d_free(file->filename);
yy_delete_buffer(file->buffer.lexer_buffer, ctx->scanner);
--ctx->file_count;
TRACE("File stack size is now %zu.\n", ctx->file_count);
}
if (ctx->expansion_count)
yy_switch_to_buffer(ctx->expansion_stack[ctx->expansion_count - 1].buffer.lexer_buffer, ctx->scanner);
else if (ctx->file_count)
yy_switch_to_buffer(ctx->file_stack[ctx->file_count - 1].buffer.lexer_buffer, ctx->scanner);
}
static int return_token(int token, YYSTYPE *lval, const char *text)
{
switch (token)
{
case T_HASHSTRING:
case T_IDENTIFIER:
case T_IDENTIFIER_PAREN:
case T_INTEGER:
case T_STRING:
case T_TEXT:
if (!(lval->string = vkd3d_strdup(text)))
return 0;
break;
}
return token;
}
static const struct preproc_text *find_arg_expansion(struct preproc_ctx *ctx, const char *s)
{
struct preproc_macro *macro;
unsigned int i;
if ((macro = preproc_get_top_macro(ctx)))
{
for (i = 0; i < macro->arg_count; ++i)
{
if (!strcmp(s, macro->arg_names[i]))
return &macro->arg_values[i];
}
}
return NULL;
}
static void preproc_text_add(struct preproc_text *text, const char *string)
{
vkd3d_string_buffer_printf(&text->text, "%s", string);
}
static bool preproc_push_expansion(struct preproc_ctx *ctx,
const struct preproc_text *text, struct preproc_macro *macro)
{
struct preproc_expansion *exp;
if (!vkd3d_array_reserve((void **)&ctx->expansion_stack, &ctx->expansion_stack_size,
ctx->expansion_count + 1, sizeof(*ctx->expansion_stack)))
return false;
exp = &ctx->expansion_stack[ctx->expansion_count++];
exp->text = text;
exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner);
exp->buffer.location = text->location;
exp->macro = macro;
TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count);
return true;
}
int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
{
struct preproc_ctx *ctx = yyget_extra(scanner);
for (;;)
{
struct preproc_func_state *func_state;
const char *text;
int token;
if (ctx->lookahead_token)
{
token = ctx->lookahead_token;
text = yyget_text(scanner);
}
else
{
if (ctx->last_was_eof)
{
preproc_pop_buffer(ctx);
if (!ctx->file_count)
return 0;
}
ctx->last_was_eof = false;
assert(ctx->file_count);
if (!(token = preproc_lexer_lex(lval, lloc, scanner)))
{
ctx->last_was_eof = true;
/* If we have reached the end of an included file, inject a newline. */
if (ctx->expansion_count)
continue;
token = T_NEWLINE;
text = "\n";
}
else
{
text = yyget_text(scanner);
}
if (ctx->last_was_newline)
{
switch (token)
{
case T_DEFINE:
case T_ELIF:
case T_ELSE:
case T_ENDIF:
case T_ERROR:
case T_IF:
case T_IFDEF:
case T_IFNDEF:
case T_INCLUDE:
case T_LINE:
case T_PRAGMA:
case T_UNDEF:
ctx->current_directive = token;
break;
default:
ctx->current_directive = 0;
}
}
ctx->last_was_newline = (token == T_NEWLINE);
}
if (ctx->current_directive && token == T_DEFINED)
ctx->last_was_defined = true;
func_state = ctx->current_directive ? &ctx->directive_func : &ctx->text_func;
TRACE("Parsing token %d%s, line %d, in directive %d, state %#x, string %s.\n",
token, ctx->lookahead_token ? " (lookahead)" : "", lloc->line,
ctx->current_directive, func_state->state, debugstr_a(text));
ctx->lookahead_token = 0;
switch (ctx->current_directive)
{
case T_ELIF:
case T_ELSE:
case T_ENDIF:
case T_IF:
case T_IFDEF:
case T_IFNDEF:
break;
default:
if (!preproc_is_writing(ctx))
continue;
}
if (ctx->current_directive == T_PRAGMA)
{
/* Print all tokens verbatim. */
if (token == T_PRAGMA)
vkd3d_string_buffer_printf(&ctx->buffer, "#pragma ");
else
vkd3d_string_buffer_printf(&ctx->buffer, "%s", text);
continue;
}
switch (func_state->state)
{
case STATE_NONE:
{
struct preproc_macro *macro;
if (token == T_CONCAT && should_concat(ctx))
{
while (ctx->buffer.content_size
&& strchr(" \t\r\n", ctx->buffer.buffer[ctx->buffer.content_size - 1]))
--ctx->buffer.content_size;
break;
}
/* Stringification, however, is only done for function-like
* macro bodies. */
if (token == T_HASHSTRING && (macro = preproc_get_top_macro(ctx)) && macro->arg_count)
{
const struct preproc_text *expansion;
const char *p = text + 1;
unsigned int i;
if (ctx->current_directive)
return return_token(token, lval, text);
while (*p == ' ' || *p == '\t')
++p;
vkd3d_string_buffer_printf(&ctx->buffer, "\"");
if ((expansion = find_arg_expansion(ctx, p)))
{
for (i = 0; i < expansion->text.content_size; ++i)
{
char c = expansion->text.buffer[i];
if (c == '\\' || c == '"')
vkd3d_string_buffer_printf(&ctx->buffer, "\\");
vkd3d_string_buffer_printf(&ctx->buffer, "%c", c);
}
}
else
{
vkd3d_string_buffer_printf(&ctx->buffer, "%s", p);
}
vkd3d_string_buffer_printf(&ctx->buffer, "\"");
break;
}
if (token == T_IDENTIFIER || token == T_IDENTIFIER_PAREN)
{
const struct preproc_text *expansion;
struct preproc_macro *macro;
switch (ctx->current_directive)
{
case T_DEFINE:
case T_IFDEF:
case T_IFNDEF:
case T_UNDEF:
/* Return identifiers verbatim. */
return return_token(token, lval, text);
case T_IF:
case T_ELIF:
/* Return identifiers verbatim only if they're the
* argument to "defined". */
if (ctx->last_was_defined)
{
ctx->last_was_defined = false;
return return_token(token, lval, text);
}
break;
}
/* Otherwise, expand a macro if there is one. */
if ((expansion = find_arg_expansion(ctx, text)))
{
preproc_push_expansion(ctx, expansion, NULL);
continue;
}
if ((macro = preproc_find_macro(ctx, text)))
{
if (!macro->arg_count)
{
preproc_push_expansion(ctx, &macro->body, macro);
}
else
{
func_state->state = STATE_IDENTIFIER;
func_state->macro = macro;
}
continue;
}
if (!strcmp(text, "__FILE__"))
{
const struct preproc_file *file = preproc_get_top_file(ctx);
/* Not the current file name, but rather the file name
* before invoking any macros. */
if (ctx->current_directive)
{
char *string;
if (!(string = vkd3d_malloc(strlen(file->filename) + 3)))
return 0;
sprintf(string, "\"%s\"", file->filename);
lval->string = string;
return T_STRING;
}
if (preproc_is_writing(ctx))
vkd3d_string_buffer_printf(&ctx->buffer, "\"%s\" ", file->filename);
continue;
}
if (!strcmp(text, "__LINE__"))
{
const struct preproc_file *file = preproc_get_top_file(ctx);
/* Not the current line number, but rather the line
* number before invoking any macros. */
if (ctx->current_directive)
{
char string[13];
sprintf(string, "%d", file->buffer.location.line);
return return_token(T_INTEGER, lval, string);
}
if (preproc_is_writing(ctx))
vkd3d_string_buffer_printf(&ctx->buffer, "%d ", file->buffer.location.line);
continue;
}
}
if (ctx->current_directive)
return return_token(token, lval, text);
vkd3d_string_buffer_printf(&ctx->buffer, "%s ", text);
break;
}
case STATE_IDENTIFIER:
if (token == '(')
{
struct preproc_text *first_arg = &func_state->macro->arg_values[0];
unsigned int i;
func_state->arg_count = 0;
func_state->paren_depth = 1;
func_state->state = STATE_ARGS;
for (i = 0; i < func_state->macro->arg_count; ++i)
func_state->macro->arg_values[i].text.content_size = 0;
first_arg->location = *lloc;
}
else
{
const char *name = func_state->macro->name;
ctx->lookahead_token = token;
func_state->macro = NULL;
func_state->state = STATE_NONE;
if (ctx->current_directive)
return return_token(T_IDENTIFIER, lval, name);
vkd3d_string_buffer_printf(&ctx->buffer, "%s ", name);
}
break;
case STATE_ARGS:
{
struct preproc_text *current_arg = NULL;
assert(func_state->macro->arg_count);
if (func_state->arg_count < func_state->macro->arg_count)
current_arg = &func_state->macro->arg_values[func_state->arg_count];
switch (token)
{
case T_NEWLINE:
if (current_arg)
preproc_text_add(current_arg, " ");
break;
case ')':
case ']':
case '}':
if (!--func_state->paren_depth)
{
if (++func_state->arg_count == func_state->macro->arg_count)
{
preproc_push_expansion(ctx, &func_state->macro->body, func_state->macro);
}
else
{
preproc_warning(ctx, lloc, VKD3D_SHADER_WARNING_PP_ARGUMENT_COUNT_MISMATCH,
"Wrong number of arguments to macro \"%s\": expected %zu, got %zu.",
func_state->macro->name, func_state->macro->arg_count, func_state->arg_count);
if (ctx->current_directive)
return return_token(T_IDENTIFIER, lval, func_state->macro->name);
vkd3d_string_buffer_printf(&ctx->buffer, "%s ", func_state->macro->name);
}
func_state->macro = NULL;
func_state->state = STATE_NONE;
}
else
{
if (current_arg)
preproc_text_add(current_arg, text);
}
break;
case ',':
if (func_state->paren_depth == 1)
{
++func_state->arg_count;
if (current_arg)
current_arg->location = *lloc;
}
else if (current_arg)
{
preproc_text_add(current_arg, text);
}
break;
case '(':
case '[':
case '{':
++func_state->paren_depth;
/* fall through */
default:
if (current_arg)
preproc_text_add(current_arg, text);
}
break;
}
}
}
}
bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct vkd3d_shader_code *code)
{
struct preproc_file *file;
if (!vkd3d_array_reserve((void **)&ctx->file_stack, &ctx->file_stack_size,
ctx->file_count + 1, sizeof(*ctx->file_stack)))
return false;
file = &ctx->file_stack[ctx->file_count++];
memset(file, 0, sizeof(*file));
file->code = *code;
file->filename = filename;
file->buffer.lexer_buffer = yy_scan_bytes(code->code, code->size, ctx->scanner);
file->buffer.location.source_name = file->filename;
file->buffer.location.line = 1;
file->buffer.location.column = 1;
TRACE("File stack size is now %zu.\n", ctx->file_count);
ctx->last_was_newline = true;
return true;
}
static int preproc_macro_compare(const void *key, const struct rb_entry *entry)
{
const struct preproc_macro *macro = RB_ENTRY_VALUE(entry, struct preproc_macro, entry);
const char *name = key;
return strcmp(name, macro->name);
}
static void preproc_macro_rb_free(struct rb_entry *entry, void *ctx)
{
preproc_free_macro(RB_ENTRY_VALUE(entry, struct preproc_macro, entry));
}
int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
static const struct vkd3d_shader_preprocess_info default_preprocess_info = {0};
struct preproc_ctx ctx = {0};
char *source_name = NULL;
void *output_code;
unsigned int i;
vkd3d_string_buffer_init(&ctx.buffer);
rb_init(&ctx.macros, preproc_macro_compare);
if (!(ctx.preprocess_info = vkd3d_find_struct(compile_info->next, PREPROCESS_INFO)))
ctx.preprocess_info = &default_preprocess_info;
ctx.message_context = message_context;
if (!(source_name = vkd3d_strdup(compile_info->source_name ? compile_info->source_name : "<anonymous>")))
goto fail;
for (i = 0; i < ctx.preprocess_info->macro_count; ++i)
{
const struct vkd3d_shader_location loc = {.source_name = source_name};
struct vkd3d_string_buffer body;
char *name;
vkd3d_string_buffer_init(&body);
vkd3d_string_buffer_printf(&body, "%s", ctx.preprocess_info->macros[i].value);
if (!(name = vkd3d_strdup(ctx.preprocess_info->macros[i].name)))
{
vkd3d_string_buffer_cleanup(&body);
goto fail;
}
if (!preproc_add_macro(&ctx, &loc, name, NULL, 0, &loc, &body))
{
vkd3d_free(name);
vkd3d_string_buffer_cleanup(&body);
goto fail;
}
}
yylex_init_extra(&ctx, &ctx.scanner);
if (!preproc_push_include(&ctx, source_name, &compile_info->source))
{
yylex_destroy(ctx.scanner);
goto fail;
}
preproc_yyparse(ctx.scanner, &ctx);
switch (ctx.text_func.state)
{
case STATE_NONE:
break;
case STATE_ARGS:
{
const struct vkd3d_shader_location loc = {.source_name = source_name};
preproc_warning(&ctx, &loc, VKD3D_SHADER_WARNING_PP_UNTERMINATED_MACRO,
"Unterminated macro invocation.");
}
/* fall through */
case STATE_IDENTIFIER:
if (preproc_is_writing(&ctx))
vkd3d_string_buffer_printf(&ctx.buffer, "%s ", ctx.text_func.macro->name);
break;
}
while (ctx.file_count)
preproc_pop_buffer(&ctx);
yylex_destroy(ctx.scanner);
rb_destroy(&ctx.macros, preproc_macro_rb_free, NULL);
vkd3d_free(ctx.file_stack);
vkd3d_free(ctx.expansion_stack);
if (ctx.error)
{
WARN("Failed to preprocess.\n");
vkd3d_string_buffer_cleanup(&ctx.buffer);
return VKD3D_ERROR_INVALID_SHADER;
}
if (!(output_code = vkd3d_malloc(ctx.buffer.content_size)))
{
vkd3d_string_buffer_cleanup(&ctx.buffer);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
memcpy(output_code, ctx.buffer.buffer, ctx.buffer.content_size);
out->size = ctx.buffer.content_size;
out->code = output_code;
vkd3d_string_buffer_trace(&ctx.buffer);
vkd3d_string_buffer_cleanup(&ctx.buffer);
return VKD3D_OK;
fail:
rb_destroy(&ctx.macros, preproc_macro_rb_free, NULL);
vkd3d_free(source_name);
vkd3d_string_buffer_cleanup(&ctx.buffer);
return VKD3D_ERROR_OUT_OF_MEMORY;
}

View File

@ -0,0 +1,829 @@
/*
* HLSL preprocessor
*
* Copyright 2020 Zebediah Figura 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
*/
%code requires
{
#include "vkd3d_shader_private.h"
#include "preproc.h"
#include <stdio.h>
#include <sys/stat.h>
#define PREPROC_YYLTYPE struct vkd3d_shader_location
struct parse_arg_names
{
char **args;
size_t count;
};
}
%code provides
{
int preproc_yylex(PREPROC_YYSTYPE *yylval_param, PREPROC_YYLTYPE *yylloc_param, void *scanner);
}
%code
{
#define YYLLOC_DEFAULT(cur, rhs, n) (cur) = YYRHSLOC(rhs, !!n)
#ifndef S_ISREG
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
static void preproc_error(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *format, ...)
{
va_list args;
va_start(args, format);
vkd3d_shader_verror(ctx->message_context, loc, error, format, args);
va_end(args);
ctx->error = true;
}
void preproc_warning(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *format, ...)
{
va_list args;
va_start(args, format);
vkd3d_shader_vwarning(ctx->message_context, loc, error, format, args);
va_end(args);
}
static void yyerror(const YYLTYPE *loc, void *scanner, struct preproc_ctx *ctx, const char *string)
{
preproc_error(ctx, loc, VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX, "%s", string);
}
struct preproc_macro *preproc_find_macro(struct preproc_ctx *ctx, const char *name)
{
struct rb_entry *entry;
if ((entry = rb_get(&ctx->macros, name)))
return RB_ENTRY_VALUE(entry, struct preproc_macro, entry);
return NULL;
}
bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_location *loc, char *name, char **arg_names,
size_t arg_count, const struct vkd3d_shader_location *body_loc, struct vkd3d_string_buffer *body)
{
struct preproc_macro *macro;
unsigned int i;
int ret;
if ((macro = preproc_find_macro(ctx, name)))
{
preproc_warning(ctx, loc, VKD3D_SHADER_WARNING_PP_ALREADY_DEFINED, "Redefinition of %s.", name);
rb_remove(&ctx->macros, &macro->entry);
preproc_free_macro(macro);
}
TRACE("Defining new macro %s with %zu arguments.\n", debugstr_a(name), arg_count);
if (!(macro = vkd3d_malloc(sizeof(*macro))))
return false;
macro->name = name;
macro->arg_names = arg_names;
macro->arg_count = arg_count;
macro->arg_values = NULL;
if (arg_count && !(macro->arg_values = vkd3d_calloc(arg_count, sizeof(*macro->arg_values))))
{
vkd3d_free(macro);
return false;
}
for (i = 0; i < arg_count; ++i)
vkd3d_string_buffer_init(&macro->arg_values[i].text);
macro->body.text = *body;
macro->body.location = *body_loc;
ret = rb_put(&ctx->macros, name, &macro->entry);
assert(!ret);
return true;
}
void preproc_free_macro(struct preproc_macro *macro)
{
unsigned int i;
vkd3d_free(macro->name);
for (i = 0; i < macro->arg_count; ++i)
{
vkd3d_string_buffer_cleanup(&macro->arg_values[i].text);
vkd3d_free(macro->arg_names[i]);
}
vkd3d_free(macro->arg_names);
vkd3d_free(macro->arg_values);
vkd3d_string_buffer_cleanup(&macro->body.text);
vkd3d_free(macro);
}
static bool preproc_was_writing(struct preproc_ctx *ctx)
{
const struct preproc_file *file = preproc_get_top_file(ctx);
/* This applies across files, since we can't #include anyway if we weren't
* writing. */
if (file->if_count < 2)
return true;
return file->if_stack[file->if_count - 2].current_true;
}
static bool preproc_push_if(struct preproc_ctx *ctx, bool condition)
{
struct preproc_file *file = preproc_get_top_file(ctx);
struct preproc_if_state *state;
if (!vkd3d_array_reserve((void **)&file->if_stack, &file->if_stack_size,
file->if_count + 1, sizeof(*file->if_stack)))
return false;
state = &file->if_stack[file->if_count++];
state->current_true = condition && preproc_was_writing(ctx);
state->seen_true = condition;
state->seen_else = false;
return true;
}
static int char_to_int(char c)
{
if ('0' <= c && c <= '9')
return c - '0';
if ('A' <= c && c <= 'F')
return c - 'A' + 10;
if ('a' <= c && c <= 'f')
return c - 'a' + 10;
return -1;
}
static uint32_t preproc_parse_integer(const char *s)
{
uint32_t base = 10, ret = 0;
int digit;
if (*s == '0')
{
base = 8;
++s;
if (*s == 'x' || *s == 'X')
{
base = 16;
++s;
}
}
while ((digit = char_to_int(*s++)) >= 0)
ret = ret * base + (uint32_t)digit;
return ret;
}
static int default_open_include(const char *filename, bool local,
const char *parent_data, void *context, struct vkd3d_shader_code *out)
{
uint8_t *data, *new_data;
size_t size = 4096;
struct stat st;
size_t pos = 0;
size_t ret;
FILE *f;
if (!(f = fopen(filename, "rb")))
{
ERR("Unable to open %s for reading.\n", debugstr_a(filename));
return VKD3D_ERROR;
}
if (fstat(fileno(f), &st) == -1)
{
ERR("Could not stat file %s.\n", debugstr_a(filename));
fclose(f);
return VKD3D_ERROR;
}
if (S_ISREG(st.st_mode))
size = st.st_size;
if (!(data = vkd3d_malloc(size)))
{
fclose(f);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
for (;;)
{
if (pos >= size)
{
if (size > SIZE_MAX / 2 || !(new_data = vkd3d_realloc(data, size * 2)))
{
vkd3d_free(data);
fclose(f);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
data = new_data;
size *= 2;
}
if (!(ret = fread(&data[pos], 1, size - pos, f)))
break;
pos += ret;
}
if (!feof(f))
{
vkd3d_free(data);
return VKD3D_ERROR;
}
fclose(f);
out->code = data;
out->size = pos;
return VKD3D_OK;
}
static void default_close_include(const struct vkd3d_shader_code *code, void *context)
{
vkd3d_free((void *)code->code);
}
void preproc_close_include(struct preproc_ctx *ctx, const struct vkd3d_shader_code *code)
{
PFN_vkd3d_shader_close_include close_include = ctx->preprocess_info->pfn_close_include;
if (!close_include)
close_include = default_close_include;
close_include(code, ctx->preprocess_info->include_context);
}
static const void *get_parent_data(struct preproc_ctx *ctx)
{
if (ctx->file_count == 1)
return NULL;
return preproc_get_top_file(ctx)->code.code;
}
static void free_parse_arg_names(struct parse_arg_names *args)
{
unsigned int i;
for (i = 0; i < args->count; ++i)
vkd3d_free(args->args[i]);
vkd3d_free(args->args);
}
}
%define api.prefix {preproc_yy}
%define api.pure full
%define parse.error verbose
%expect 0
%locations
%lex-param {yyscan_t scanner}
%parse-param {void *scanner}
%parse-param {struct preproc_ctx *ctx}
%union
{
char *string;
const char *const_string;
uint32_t integer;
struct vkd3d_string_buffer string_buffer;
struct parse_arg_names arg_names;
}
%token <string> T_HASHSTRING
%token <string> T_IDENTIFIER
%token <string> T_IDENTIFIER_PAREN
%token <string> T_INTEGER
%token <string> T_STRING
%token <string> T_TEXT
%token T_NEWLINE
%token T_DEFINE "#define"
%token T_ERROR "#error"
%token T_ELIF "#elif"
%token T_ELSE "#else"
%token T_ENDIF "#endif"
%token T_IF "#if"
%token T_IFDEF "#ifdef"
%token T_IFNDEF "#ifndef"
%token T_INCLUDE "#include"
%token T_LINE "#line"
%token T_PRAGMA "#pragma"
%token T_UNDEF "#undef"
%token T_CONCAT "##"
%token T_LE "<="
%token T_GE ">="
%token T_EQ "=="
%token T_NE "!="
%token T_AND "&&"
%token T_OR "||"
%token T_DEFINED "defined"
%type <integer> primary_expr
%type <integer> unary_expr
%type <integer> mul_expr
%type <integer> add_expr
%type <integer> ineq_expr
%type <integer> eq_expr
%type <integer> bitand_expr
%type <integer> bitxor_expr
%type <integer> bitor_expr
%type <integer> logicand_expr
%type <integer> logicor_expr
%type <integer> expr
%type <string> body_token
%type <const_string> body_token_const
%type <string_buffer> body_text
%type <arg_names> identifier_list
%%
shader_text
: %empty
| shader_text directive
{
vkd3d_string_buffer_printf(&ctx->buffer, "\n");
}
identifier_list
: T_IDENTIFIER
{
if (!($$.args = vkd3d_malloc(sizeof(*$$.args))))
YYABORT;
$$.args[0] = $1;
$$.count = 1;
}
| identifier_list ',' T_IDENTIFIER
{
char **new_array;
if (!(new_array = vkd3d_realloc($1.args, ($1.count + 1) * sizeof(*$$.args))))
{
free_parse_arg_names(&$1);
YYABORT;
}
$$.args = new_array;
$$.count = $1.count + 1;
$$.args[$1.count] = $3;
}
body_text
: %empty
{
vkd3d_string_buffer_init(&$$);
}
| body_text body_token
{
if (vkd3d_string_buffer_printf(&$$, "%s ", $2) < 0)
{
vkd3d_free($2);
YYABORT;
}
vkd3d_free($2);
}
| body_text body_token_const
{
if (vkd3d_string_buffer_printf(&$$, "%s ", $2) < 0)
YYABORT;
}
body_token
: T_HASHSTRING
| T_IDENTIFIER
| T_IDENTIFIER_PAREN
| T_INTEGER
| T_TEXT
body_token_const
: '('
{
$$ = "(";
}
| ')'
{
$$ = ")";
}
| '['
{
$$ = "[";
}
| ']'
{
$$ = "]";
}
| '{'
{
$$ = "{";
}
| '}'
{
$$ = "}";
}
| ','
{
$$ = ",";
}
| '+'
{
$$ = "+";
}
| '-'
{
$$ = "-";
}
| '!'
{
$$ = "!";
}
| '*'
{
$$ = "*";
}
| '/'
{
$$ = "/";
}
| '<'
{
$$ = "<";
}
| '>'
{
$$ = ">";
}
| '&'
{
$$ = "&";
}
| '|'
{
$$ = "|";
}
| '^'
{
$$ = "^";
}
| '?'
{
$$ = "?";
}
| ':'
{
$$ = ":";
}
| T_CONCAT
{
$$ = "##";
}
| T_LE
{
$$ = "<=";
}
| T_GE
{
$$ = ">=";
}
| T_EQ
{
$$ = "==";
}
| T_NE
{
$$ = "!=";
}
| T_AND
{
$$ = "&&";
}
| T_OR
{
$$ = "||";
}
| T_DEFINED
{
$$ = "defined";
}
directive
: T_DEFINE T_IDENTIFIER body_text T_NEWLINE
{
if (!preproc_add_macro(ctx, &@$, $2, NULL, 0, &@3, &$3))
{
vkd3d_free($2);
vkd3d_string_buffer_cleanup(&$3);
YYABORT;
}
}
| T_DEFINE T_IDENTIFIER_PAREN '(' identifier_list ')' body_text T_NEWLINE
{
if (!preproc_add_macro(ctx, &@6, $2, $4.args, $4.count, &@6, &$6))
{
vkd3d_free($2);
free_parse_arg_names(&$4);
vkd3d_string_buffer_cleanup(&$6);
YYABORT;
}
}
| T_UNDEF T_IDENTIFIER T_NEWLINE
{
struct preproc_macro *macro;
if ((macro = preproc_find_macro(ctx, $2)))
{
TRACE("Removing macro definition %s.\n", debugstr_a($2));
rb_remove(&ctx->macros, &macro->entry);
preproc_free_macro(macro);
}
vkd3d_free($2);
}
| T_IF expr T_NEWLINE
{
if (!preproc_push_if(ctx, !!$2))
YYABORT;
}
| T_IFDEF T_IDENTIFIER T_NEWLINE
{
preproc_push_if(ctx, !!preproc_find_macro(ctx, $2));
vkd3d_free($2);
}
| T_IFNDEF T_IDENTIFIER T_NEWLINE
{
preproc_push_if(ctx, !preproc_find_macro(ctx, $2));
vkd3d_free($2);
}
| T_ELIF expr T_NEWLINE
{
const struct preproc_file *file = preproc_get_top_file(ctx);
if (file->if_count)
{
struct preproc_if_state *state = &file->if_stack[file->if_count - 1];
if (state->seen_else)
{
preproc_warning(ctx, &@$, VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE, "Ignoring #elif after #else.");
}
else
{
state->current_true = $2 && !state->seen_true && preproc_was_writing(ctx);
state->seen_true = $2 || state->seen_true;
}
}
else
{
preproc_warning(ctx, &@$, VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE,
"Ignoring #elif without prior #if.");
}
}
| T_ELSE T_NEWLINE
{
const struct preproc_file *file = preproc_get_top_file(ctx);
if (file->if_count)
{
struct preproc_if_state *state = &file->if_stack[file->if_count - 1];
if (state->seen_else)
{
preproc_warning(ctx, &@$, VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE, "Ignoring #else after #else.");
}
else
{
state->current_true = !state->seen_true && preproc_was_writing(ctx);
state->seen_else = true;
}
}
else
{
preproc_warning(ctx, &@$, VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE,
"Ignoring #else without prior #if.");
}
}
| T_ENDIF T_NEWLINE
{
struct preproc_file *file = preproc_get_top_file(ctx);
if (file->if_count)
--file->if_count;
else
preproc_warning(ctx, &@$, VKD3D_SHADER_WARNING_PP_INVALID_DIRECTIVE,
"Ignoring #endif without prior #if.");
}
| T_ERROR T_NEWLINE
{
preproc_error(ctx, &@$, VKD3D_SHADER_ERROR_PP_ERROR_DIRECTIVE, "Error directive.");
}
| T_ERROR T_STRING T_NEWLINE
{
preproc_error(ctx, &@$, VKD3D_SHADER_ERROR_PP_ERROR_DIRECTIVE, "Error directive: %s", $2);
vkd3d_free($2);
}
| T_INCLUDE T_STRING T_NEWLINE
{
PFN_vkd3d_shader_open_include open_include = ctx->preprocess_info->pfn_open_include;
struct vkd3d_shader_code code;
char *filename;
int result;
if (!(filename = vkd3d_malloc(strlen($2) - 1)))
YYABORT;
if (!open_include)
open_include = default_open_include;
memcpy(filename, $2 + 1, strlen($2) - 2);
filename[strlen($2) - 2] = 0;
if (!(result = open_include(filename, $2[0] == '"', get_parent_data(ctx),
ctx->preprocess_info->include_context, &code)))
{
if (!preproc_push_include(ctx, filename, &code))
{
preproc_close_include(ctx, &code);
vkd3d_free(filename);
}
}
else
{
preproc_error(ctx, &@$, VKD3D_SHADER_ERROR_PP_INCLUDE_FAILED, "Failed to open %s.", $2);
vkd3d_free(filename);
}
vkd3d_free($2);
}
| T_LINE T_INTEGER T_NEWLINE
{
FIXME("#line directive.\n");
vkd3d_free($2);
}
| T_LINE T_INTEGER T_STRING T_NEWLINE
{
FIXME("#line directive.\n");
vkd3d_free($2);
vkd3d_free($3);
}
primary_expr
: T_INTEGER
{
$$ = preproc_parse_integer($1);
vkd3d_free($1);
}
| T_IDENTIFIER
{
$$ = 0;
vkd3d_free($1);
}
| T_DEFINED T_IDENTIFIER
{
$$ = !!preproc_find_macro(ctx, $2);
vkd3d_free($2);
}
| T_DEFINED '(' T_IDENTIFIER ')'
{
$$ = !!preproc_find_macro(ctx, $3);
vkd3d_free($3);
}
| '(' expr ')'
{
$$ = $2;
}
unary_expr
: primary_expr
| '+' unary_expr
{
$$ = $2;
}
| '-' unary_expr
{
$$ = -$2;
}
| '!' unary_expr
{
$$ = !$2;
}
mul_expr
: unary_expr
| mul_expr '*' unary_expr
{
$$ = $1 * $3;
}
| mul_expr '/' unary_expr
{
if (!$3)
{
preproc_warning(ctx, &@3, VKD3D_SHADER_WARNING_PP_DIV_BY_ZERO, "Division by zero.");
$3 = 1;
}
$$ = $1 / $3;
}
add_expr
: mul_expr
| add_expr '+' mul_expr
{
$$ = $1 + $3;
}
| add_expr '-' mul_expr
{
$$ = $1 - $3;
}
ineq_expr
: add_expr
| ineq_expr '<' add_expr
{
$$ = $1 < $3;
}
| ineq_expr '>' add_expr
{
$$ = $1 > $3;
}
| ineq_expr T_LE add_expr
{
$$ = $1 <= $3;
}
| ineq_expr T_GE add_expr
{
$$ = $1 >= $3;
}
eq_expr
: ineq_expr
| eq_expr T_EQ ineq_expr
{
$$ = $1 == $3;
}
| eq_expr T_NE ineq_expr
{
$$ = $1 != $3;
}
bitand_expr
: eq_expr
| bitand_expr '&' eq_expr
{
$$ = $1 & $3;
}
bitxor_expr
: bitand_expr
| bitxor_expr '^' bitand_expr
{
$$ = $1 ^ $3;
}
bitor_expr
: bitxor_expr
| bitor_expr '|' bitxor_expr
{
$$ = $1 | $3;
}
logicand_expr
: bitor_expr
| logicand_expr T_AND bitor_expr
{
$$ = $1 && $3;
}
logicor_expr
: logicand_expr
| logicor_expr T_OR logicand_expr
{
$$ = $1 || $3;
}
expr
: logicor_expr
| expr '?' logicor_expr ':' logicor_expr
{
$$ = $1 ? $3 : $5;
}

View File

@ -0,0 +1,548 @@
/*
* Copyright 2009 Henri Verbeet 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_SM4_H
#define __VKD3D_SM4_H
#define VKD3D_SM4_PS 0x0000u
#define VKD3D_SM4_VS 0x0001u
#define VKD3D_SM4_GS 0x0002u
#define VKD3D_SM5_HS 0x0003u
#define VKD3D_SM5_DS 0x0004u
#define VKD3D_SM5_CS 0x0005u
#define VKD3D_SM4_LIB 0xfff0u
#define VKD3D_SM4_INSTRUCTION_MODIFIER (0x1u << 31)
#define VKD3D_SM4_MODIFIER_MASK 0x3fu
#define VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT 6
#define VKD3D_SM5_MODIFIER_DATA_TYPE_MASK (0xffffu << VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT)
#define VKD3D_SM5_MODIFIER_RESOURCE_TYPE_SHIFT 6
#define VKD3D_SM5_MODIFIER_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM5_MODIFIER_RESOURCE_TYPE_SHIFT)
#define VKD3D_SM5_MODIFIER_RESOURCE_STRIDE_SHIFT 11
#define VKD3D_SM5_MODIFIER_RESOURCE_STRIDE_MASK (0xfffu << VKD3D_SM5_MODIFIER_RESOURCE_STRIDE_SHIFT)
#define VKD3D_SM4_AOFFIMMI_U_SHIFT 9
#define VKD3D_SM4_AOFFIMMI_U_MASK (0xfu << VKD3D_SM4_AOFFIMMI_U_SHIFT)
#define VKD3D_SM4_AOFFIMMI_V_SHIFT 13
#define VKD3D_SM4_AOFFIMMI_V_MASK (0xfu << VKD3D_SM4_AOFFIMMI_V_SHIFT)
#define VKD3D_SM4_AOFFIMMI_W_SHIFT 17
#define VKD3D_SM4_AOFFIMMI_W_MASK (0xfu << VKD3D_SM4_AOFFIMMI_W_SHIFT)
#define VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT 24
#define VKD3D_SM4_INSTRUCTION_LENGTH_MASK (0x1fu << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT)
#define VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT 11
#define VKD3D_SM4_INSTRUCTION_FLAGS_MASK (0x7u << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT)
#define VKD3D_SM4_RESOURCE_TYPE_SHIFT 11
#define VKD3D_SM4_RESOURCE_TYPE_MASK (0xfu << VKD3D_SM4_RESOURCE_TYPE_SHIFT)
#define VKD3D_SM4_PRIMITIVE_TYPE_SHIFT 11
#define VKD3D_SM4_PRIMITIVE_TYPE_MASK (0x3fu << VKD3D_SM4_PRIMITIVE_TYPE_SHIFT)
#define VKD3D_SM4_INDEX_TYPE_SHIFT 11
#define VKD3D_SM4_INDEX_TYPE_MASK (0x1u << VKD3D_SM4_INDEX_TYPE_SHIFT)
#define VKD3D_SM4_SAMPLER_MODE_SHIFT 11
#define VKD3D_SM4_SAMPLER_MODE_MASK (0xfu << VKD3D_SM4_SAMPLER_MODE_SHIFT)
#define VKD3D_SM4_SHADER_DATA_TYPE_SHIFT 11
#define VKD3D_SM4_SHADER_DATA_TYPE_MASK (0xfu << VKD3D_SM4_SHADER_DATA_TYPE_SHIFT)
#define VKD3D_SM4_INTERPOLATION_MODE_SHIFT 11
#define VKD3D_SM4_INTERPOLATION_MODE_MASK (0xfu << VKD3D_SM4_INTERPOLATION_MODE_SHIFT)
#define VKD3D_SM4_GLOBAL_FLAGS_SHIFT 11
#define VKD3D_SM4_GLOBAL_FLAGS_MASK (0xffu << VKD3D_SM4_GLOBAL_FLAGS_SHIFT)
#define VKD3D_SM5_PRECISE_SHIFT 19
#define VKD3D_SM5_PRECISE_MASK (0xfu << VKD3D_SM5_PRECISE_SHIFT)
#define VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT 11
#define VKD3D_SM5_CONTROL_POINT_COUNT_MASK (0xffu << VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT)
#define VKD3D_SM5_FP_ARRAY_SIZE_SHIFT 16
#define VKD3D_SM5_FP_TABLE_COUNT_MASK 0xffffu
#define VKD3D_SM5_UAV_FLAGS_SHIFT 15
#define VKD3D_SM5_UAV_FLAGS_MASK (0x1ffu << VKD3D_SM5_UAV_FLAGS_SHIFT)
#define VKD3D_SM5_SYNC_FLAGS_SHIFT 11
#define VKD3D_SM5_SYNC_FLAGS_MASK (0xffu << VKD3D_SM5_SYNC_FLAGS_SHIFT)
#define VKD3D_SM5_TESSELLATOR_SHIFT 11
#define VKD3D_SM5_TESSELLATOR_MASK (0xfu << VKD3D_SM5_TESSELLATOR_SHIFT)
#define VKD3D_SM4_OPCODE_MASK 0xff
#define VKD3D_SM4_EXTENDED_OPERAND (0x1u << 31)
#define VKD3D_SM4_EXTENDED_OPERAND_TYPE_MASK 0x3fu
#define VKD3D_SM4_REGISTER_MODIFIER_SHIFT 6
#define VKD3D_SM4_REGISTER_MODIFIER_MASK (0xffu << VKD3D_SM4_REGISTER_MODIFIER_SHIFT)
#define VKD3D_SM4_REGISTER_PRECISION_SHIFT 14
#define VKD3D_SM4_REGISTER_PRECISION_MASK (0x7u << VKD3D_SM4_REGISTER_PRECISION_SHIFT)
#define VKD3D_SM4_REGISTER_NON_UNIFORM_SHIFT 17
#define VKD3D_SM4_REGISTER_NON_UNIFORM_MASK (0x1u << VKD3D_SM4_REGISTER_NON_UNIFORM_SHIFT)
#define VKD3D_SM4_ADDRESSING_SHIFT2 28
#define VKD3D_SM4_ADDRESSING_MASK2 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT2)
#define VKD3D_SM4_ADDRESSING_SHIFT1 25
#define VKD3D_SM4_ADDRESSING_MASK1 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT1)
#define VKD3D_SM4_ADDRESSING_SHIFT0 22
#define VKD3D_SM4_ADDRESSING_MASK0 (0x3u << VKD3D_SM4_ADDRESSING_SHIFT0)
#define VKD3D_SM4_REGISTER_ORDER_SHIFT 20
#define VKD3D_SM4_REGISTER_ORDER_MASK (0x3u << VKD3D_SM4_REGISTER_ORDER_SHIFT)
#define VKD3D_SM4_REGISTER_TYPE_SHIFT 12
#define VKD3D_SM4_REGISTER_TYPE_MASK (0xffu << VKD3D_SM4_REGISTER_TYPE_SHIFT)
#define VKD3D_SM4_SWIZZLE_TYPE_SHIFT 2
#define VKD3D_SM4_SWIZZLE_TYPE_MASK (0x3u << VKD3D_SM4_SWIZZLE_TYPE_SHIFT)
#define VKD3D_SM4_DIMENSION_SHIFT 0
#define VKD3D_SM4_DIMENSION_MASK (0x3u << VKD3D_SM4_DIMENSION_SHIFT)
#define VKD3D_SM4_WRITEMASK_SHIFT 4
#define VKD3D_SM4_WRITEMASK_MASK (0xfu << VKD3D_SM4_WRITEMASK_SHIFT)
#define VKD3D_SM4_SWIZZLE_SHIFT 4
#define VKD3D_SM4_SWIZZLE_MASK (0xffu << VKD3D_SM4_SWIZZLE_SHIFT)
#define VKD3D_SM4_VERSION_MAJOR(version) (((version) >> 4) & 0xf)
#define VKD3D_SM4_VERSION_MINOR(version) (((version) >> 0) & 0xf)
#define VKD3D_SM4_ADDRESSING_RELATIVE 0x2
#define VKD3D_SM4_ADDRESSING_OFFSET 0x1
#define VKD3D_SM4_INSTRUCTION_FLAG_SATURATE 0x4
#define VKD3D_SM4_CONDITIONAL_NZ (0x1u << 18)
#define VKD3D_SM4_TYPE_COMPONENT(com, i) (((com) >> (4 * (i))) & 0xfu)
/* The shift that corresponds to the D3D_SIF_TEXTURE_COMPONENTS mask. */
#define VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT 2
enum vkd3d_sm4_opcode
{
VKD3D_SM4_OP_ADD = 0x00,
VKD3D_SM4_OP_AND = 0x01,
VKD3D_SM4_OP_BREAK = 0x02,
VKD3D_SM4_OP_BREAKC = 0x03,
VKD3D_SM4_OP_CASE = 0x06,
VKD3D_SM4_OP_CONTINUE = 0x07,
VKD3D_SM4_OP_CONTINUEC = 0x08,
VKD3D_SM4_OP_CUT = 0x09,
VKD3D_SM4_OP_DEFAULT = 0x0a,
VKD3D_SM4_OP_DERIV_RTX = 0x0b,
VKD3D_SM4_OP_DERIV_RTY = 0x0c,
VKD3D_SM4_OP_DISCARD = 0x0d,
VKD3D_SM4_OP_DIV = 0x0e,
VKD3D_SM4_OP_DP2 = 0x0f,
VKD3D_SM4_OP_DP3 = 0x10,
VKD3D_SM4_OP_DP4 = 0x11,
VKD3D_SM4_OP_ELSE = 0x12,
VKD3D_SM4_OP_EMIT = 0x13,
VKD3D_SM4_OP_ENDIF = 0x15,
VKD3D_SM4_OP_ENDLOOP = 0x16,
VKD3D_SM4_OP_ENDSWITCH = 0x17,
VKD3D_SM4_OP_EQ = 0x18,
VKD3D_SM4_OP_EXP = 0x19,
VKD3D_SM4_OP_FRC = 0x1a,
VKD3D_SM4_OP_FTOI = 0x1b,
VKD3D_SM4_OP_FTOU = 0x1c,
VKD3D_SM4_OP_GE = 0x1d,
VKD3D_SM4_OP_IADD = 0x1e,
VKD3D_SM4_OP_IF = 0x1f,
VKD3D_SM4_OP_IEQ = 0x20,
VKD3D_SM4_OP_IGE = 0x21,
VKD3D_SM4_OP_ILT = 0x22,
VKD3D_SM4_OP_IMAD = 0x23,
VKD3D_SM4_OP_IMAX = 0x24,
VKD3D_SM4_OP_IMIN = 0x25,
VKD3D_SM4_OP_IMUL = 0x26,
VKD3D_SM4_OP_INE = 0x27,
VKD3D_SM4_OP_INEG = 0x28,
VKD3D_SM4_OP_ISHL = 0x29,
VKD3D_SM4_OP_ISHR = 0x2a,
VKD3D_SM4_OP_ITOF = 0x2b,
VKD3D_SM4_OP_LABEL = 0x2c,
VKD3D_SM4_OP_LD = 0x2d,
VKD3D_SM4_OP_LD2DMS = 0x2e,
VKD3D_SM4_OP_LOG = 0x2f,
VKD3D_SM4_OP_LOOP = 0x30,
VKD3D_SM4_OP_LT = 0x31,
VKD3D_SM4_OP_MAD = 0x32,
VKD3D_SM4_OP_MIN = 0x33,
VKD3D_SM4_OP_MAX = 0x34,
VKD3D_SM4_OP_SHADER_DATA = 0x35,
VKD3D_SM4_OP_MOV = 0x36,
VKD3D_SM4_OP_MOVC = 0x37,
VKD3D_SM4_OP_MUL = 0x38,
VKD3D_SM4_OP_NE = 0x39,
VKD3D_SM4_OP_NOP = 0x3a,
VKD3D_SM4_OP_NOT = 0x3b,
VKD3D_SM4_OP_OR = 0x3c,
VKD3D_SM4_OP_RESINFO = 0x3d,
VKD3D_SM4_OP_RET = 0x3e,
VKD3D_SM4_OP_RETC = 0x3f,
VKD3D_SM4_OP_ROUND_NE = 0x40,
VKD3D_SM4_OP_ROUND_NI = 0x41,
VKD3D_SM4_OP_ROUND_PI = 0x42,
VKD3D_SM4_OP_ROUND_Z = 0x43,
VKD3D_SM4_OP_RSQ = 0x44,
VKD3D_SM4_OP_SAMPLE = 0x45,
VKD3D_SM4_OP_SAMPLE_C = 0x46,
VKD3D_SM4_OP_SAMPLE_C_LZ = 0x47,
VKD3D_SM4_OP_SAMPLE_LOD = 0x48,
VKD3D_SM4_OP_SAMPLE_GRAD = 0x49,
VKD3D_SM4_OP_SAMPLE_B = 0x4a,
VKD3D_SM4_OP_SQRT = 0x4b,
VKD3D_SM4_OP_SWITCH = 0x4c,
VKD3D_SM4_OP_SINCOS = 0x4d,
VKD3D_SM4_OP_UDIV = 0x4e,
VKD3D_SM4_OP_ULT = 0x4f,
VKD3D_SM4_OP_UGE = 0x50,
VKD3D_SM4_OP_UMUL = 0x51,
VKD3D_SM4_OP_UMAX = 0x53,
VKD3D_SM4_OP_UMIN = 0x54,
VKD3D_SM4_OP_USHR = 0x55,
VKD3D_SM4_OP_UTOF = 0x56,
VKD3D_SM4_OP_XOR = 0x57,
VKD3D_SM4_OP_DCL_RESOURCE = 0x58,
VKD3D_SM4_OP_DCL_CONSTANT_BUFFER = 0x59,
VKD3D_SM4_OP_DCL_SAMPLER = 0x5a,
VKD3D_SM4_OP_DCL_INDEX_RANGE = 0x5b,
VKD3D_SM4_OP_DCL_OUTPUT_TOPOLOGY = 0x5c,
VKD3D_SM4_OP_DCL_INPUT_PRIMITIVE = 0x5d,
VKD3D_SM4_OP_DCL_VERTICES_OUT = 0x5e,
VKD3D_SM4_OP_DCL_INPUT = 0x5f,
VKD3D_SM4_OP_DCL_INPUT_SGV = 0x60,
VKD3D_SM4_OP_DCL_INPUT_SIV = 0x61,
VKD3D_SM4_OP_DCL_INPUT_PS = 0x62,
VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63,
VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64,
VKD3D_SM4_OP_DCL_OUTPUT = 0x65,
VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67,
VKD3D_SM4_OP_DCL_TEMPS = 0x68,
VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69,
VKD3D_SM4_OP_DCL_GLOBAL_FLAGS = 0x6a,
VKD3D_SM4_OP_LOD = 0x6c,
VKD3D_SM4_OP_GATHER4 = 0x6d,
VKD3D_SM4_OP_SAMPLE_POS = 0x6e,
VKD3D_SM4_OP_SAMPLE_INFO = 0x6f,
VKD3D_SM5_OP_HS_DECLS = 0x71,
VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE = 0x72,
VKD3D_SM5_OP_HS_FORK_PHASE = 0x73,
VKD3D_SM5_OP_HS_JOIN_PHASE = 0x74,
VKD3D_SM5_OP_EMIT_STREAM = 0x75,
VKD3D_SM5_OP_CUT_STREAM = 0x76,
VKD3D_SM5_OP_FCALL = 0x78,
VKD3D_SM5_OP_BUFINFO = 0x79,
VKD3D_SM5_OP_DERIV_RTX_COARSE = 0x7a,
VKD3D_SM5_OP_DERIV_RTX_FINE = 0x7b,
VKD3D_SM5_OP_DERIV_RTY_COARSE = 0x7c,
VKD3D_SM5_OP_DERIV_RTY_FINE = 0x7d,
VKD3D_SM5_OP_GATHER4_C = 0x7e,
VKD3D_SM5_OP_GATHER4_PO = 0x7f,
VKD3D_SM5_OP_GATHER4_PO_C = 0x80,
VKD3D_SM5_OP_RCP = 0x81,
VKD3D_SM5_OP_F32TOF16 = 0x82,
VKD3D_SM5_OP_F16TOF32 = 0x83,
VKD3D_SM5_OP_COUNTBITS = 0x86,
VKD3D_SM5_OP_FIRSTBIT_HI = 0x87,
VKD3D_SM5_OP_FIRSTBIT_LO = 0x88,
VKD3D_SM5_OP_FIRSTBIT_SHI = 0x89,
VKD3D_SM5_OP_UBFE = 0x8a,
VKD3D_SM5_OP_IBFE = 0x8b,
VKD3D_SM5_OP_BFI = 0x8c,
VKD3D_SM5_OP_BFREV = 0x8d,
VKD3D_SM5_OP_SWAPC = 0x8e,
VKD3D_SM5_OP_DCL_STREAM = 0x8f,
VKD3D_SM5_OP_DCL_FUNCTION_BODY = 0x90,
VKD3D_SM5_OP_DCL_FUNCTION_TABLE = 0x91,
VKD3D_SM5_OP_DCL_INTERFACE = 0x92,
VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT = 0x93,
VKD3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT = 0x94,
VKD3D_SM5_OP_DCL_TESSELLATOR_DOMAIN = 0x95,
VKD3D_SM5_OP_DCL_TESSELLATOR_PARTITIONING = 0x96,
VKD3D_SM5_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE = 0x97,
VKD3D_SM5_OP_DCL_HS_MAX_TESSFACTOR = 0x98,
VKD3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT = 0x99,
VKD3D_SM5_OP_DCL_HS_JOIN_PHASE_INSTANCE_COUNT = 0x9a,
VKD3D_SM5_OP_DCL_THREAD_GROUP = 0x9b,
VKD3D_SM5_OP_DCL_UAV_TYPED = 0x9c,
VKD3D_SM5_OP_DCL_UAV_RAW = 0x9d,
VKD3D_SM5_OP_DCL_UAV_STRUCTURED = 0x9e,
VKD3D_SM5_OP_DCL_TGSM_RAW = 0x9f,
VKD3D_SM5_OP_DCL_TGSM_STRUCTURED = 0xa0,
VKD3D_SM5_OP_DCL_RESOURCE_RAW = 0xa1,
VKD3D_SM5_OP_DCL_RESOURCE_STRUCTURED = 0xa2,
VKD3D_SM5_OP_LD_UAV_TYPED = 0xa3,
VKD3D_SM5_OP_STORE_UAV_TYPED = 0xa4,
VKD3D_SM5_OP_LD_RAW = 0xa5,
VKD3D_SM5_OP_STORE_RAW = 0xa6,
VKD3D_SM5_OP_LD_STRUCTURED = 0xa7,
VKD3D_SM5_OP_STORE_STRUCTURED = 0xa8,
VKD3D_SM5_OP_ATOMIC_AND = 0xa9,
VKD3D_SM5_OP_ATOMIC_OR = 0xaa,
VKD3D_SM5_OP_ATOMIC_XOR = 0xab,
VKD3D_SM5_OP_ATOMIC_CMP_STORE = 0xac,
VKD3D_SM5_OP_ATOMIC_IADD = 0xad,
VKD3D_SM5_OP_ATOMIC_IMAX = 0xae,
VKD3D_SM5_OP_ATOMIC_IMIN = 0xaf,
VKD3D_SM5_OP_ATOMIC_UMAX = 0xb0,
VKD3D_SM5_OP_ATOMIC_UMIN = 0xb1,
VKD3D_SM5_OP_IMM_ATOMIC_ALLOC = 0xb2,
VKD3D_SM5_OP_IMM_ATOMIC_CONSUME = 0xb3,
VKD3D_SM5_OP_IMM_ATOMIC_IADD = 0xb4,
VKD3D_SM5_OP_IMM_ATOMIC_AND = 0xb5,
VKD3D_SM5_OP_IMM_ATOMIC_OR = 0xb6,
VKD3D_SM5_OP_IMM_ATOMIC_XOR = 0xb7,
VKD3D_SM5_OP_IMM_ATOMIC_EXCH = 0xb8,
VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH = 0xb9,
VKD3D_SM5_OP_IMM_ATOMIC_IMAX = 0xba,
VKD3D_SM5_OP_IMM_ATOMIC_IMIN = 0xbb,
VKD3D_SM5_OP_IMM_ATOMIC_UMAX = 0xbc,
VKD3D_SM5_OP_IMM_ATOMIC_UMIN = 0xbd,
VKD3D_SM5_OP_SYNC = 0xbe,
VKD3D_SM5_OP_DADD = 0xbf,
VKD3D_SM5_OP_DMAX = 0xc0,
VKD3D_SM5_OP_DMIN = 0xc1,
VKD3D_SM5_OP_DMUL = 0xc2,
VKD3D_SM5_OP_DEQ = 0xc3,
VKD3D_SM5_OP_DGE = 0xc4,
VKD3D_SM5_OP_DLT = 0xc5,
VKD3D_SM5_OP_DNE = 0xc6,
VKD3D_SM5_OP_DMOV = 0xc7,
VKD3D_SM5_OP_DMOVC = 0xc8,
VKD3D_SM5_OP_DTOF = 0xc9,
VKD3D_SM5_OP_FTOD = 0xca,
VKD3D_SM5_OP_EVAL_SAMPLE_INDEX = 0xcc,
VKD3D_SM5_OP_EVAL_CENTROID = 0xcd,
VKD3D_SM5_OP_DCL_GS_INSTANCES = 0xce,
VKD3D_SM5_OP_DDIV = 0xd2,
VKD3D_SM5_OP_DFMA = 0xd3,
VKD3D_SM5_OP_DRCP = 0xd4,
VKD3D_SM5_OP_DTOI = 0xd6,
VKD3D_SM5_OP_DTOU = 0xd7,
VKD3D_SM5_OP_ITOD = 0xd8,
VKD3D_SM5_OP_UTOD = 0xd9,
VKD3D_SM5_OP_GATHER4_S = 0xdb,
VKD3D_SM5_OP_GATHER4_C_S = 0xdc,
VKD3D_SM5_OP_GATHER4_PO_S = 0xdd,
VKD3D_SM5_OP_GATHER4_PO_C_S = 0xde,
VKD3D_SM5_OP_LD_S = 0xdf,
VKD3D_SM5_OP_LD2DMS_S = 0xe0,
VKD3D_SM5_OP_LD_UAV_TYPED_S = 0xe1,
VKD3D_SM5_OP_LD_RAW_S = 0xe2,
VKD3D_SM5_OP_LD_STRUCTURED_S = 0xe3,
VKD3D_SM5_OP_SAMPLE_LOD_S = 0xe4,
VKD3D_SM5_OP_SAMPLE_C_LZ_S = 0xe5,
VKD3D_SM5_OP_SAMPLE_CL_S = 0xe6,
VKD3D_SM5_OP_SAMPLE_B_CL_S = 0xe7,
VKD3D_SM5_OP_SAMPLE_GRAD_CL_S = 0xe8,
VKD3D_SM5_OP_SAMPLE_C_CL_S = 0xe9,
VKD3D_SM5_OP_CHECK_ACCESS_FULLY_MAPPED = 0xea,
};
enum vkd3d_sm4_instruction_modifier
{
VKD3D_SM4_MODIFIER_AOFFIMMI = 0x1,
VKD3D_SM5_MODIFIER_RESOURCE_TYPE = 0x2,
VKD3D_SM5_MODIFIER_DATA_TYPE = 0x3,
};
enum vkd3d_sm4_register_type
{
VKD3D_SM4_RT_TEMP = 0x00,
VKD3D_SM4_RT_INPUT = 0x01,
VKD3D_SM4_RT_OUTPUT = 0x02,
VKD3D_SM4_RT_INDEXABLE_TEMP = 0x03,
VKD3D_SM4_RT_IMMCONST = 0x04,
VKD3D_SM4_RT_IMMCONST64 = 0x05,
VKD3D_SM4_RT_SAMPLER = 0x06,
VKD3D_SM4_RT_RESOURCE = 0x07,
VKD3D_SM4_RT_CONSTBUFFER = 0x08,
VKD3D_SM4_RT_IMMCONSTBUFFER = 0x09,
VKD3D_SM4_RT_PRIMID = 0x0b,
VKD3D_SM4_RT_DEPTHOUT = 0x0c,
VKD3D_SM4_RT_NULL = 0x0d,
VKD3D_SM4_RT_RASTERIZER = 0x0e,
VKD3D_SM4_RT_OMASK = 0x0f,
VKD3D_SM5_RT_STREAM = 0x10,
VKD3D_SM5_RT_FUNCTION_BODY = 0x11,
VKD3D_SM5_RT_FUNCTION_POINTER = 0x13,
VKD3D_SM5_RT_OUTPUT_CONTROL_POINT_ID = 0x16,
VKD3D_SM5_RT_FORK_INSTANCE_ID = 0x17,
VKD3D_SM5_RT_JOIN_INSTANCE_ID = 0x18,
VKD3D_SM5_RT_INPUT_CONTROL_POINT = 0x19,
VKD3D_SM5_RT_OUTPUT_CONTROL_POINT = 0x1a,
VKD3D_SM5_RT_PATCH_CONSTANT_DATA = 0x1b,
VKD3D_SM5_RT_DOMAIN_LOCATION = 0x1c,
VKD3D_SM5_RT_UAV = 0x1e,
VKD3D_SM5_RT_SHARED_MEMORY = 0x1f,
VKD3D_SM5_RT_THREAD_ID = 0x20,
VKD3D_SM5_RT_THREAD_GROUP_ID = 0x21,
VKD3D_SM5_RT_LOCAL_THREAD_ID = 0x22,
VKD3D_SM5_RT_COVERAGE = 0x23,
VKD3D_SM5_RT_LOCAL_THREAD_INDEX = 0x24,
VKD3D_SM5_RT_GS_INSTANCE_ID = 0x25,
VKD3D_SM5_RT_DEPTHOUT_GREATER_EQUAL = 0x26,
VKD3D_SM5_RT_DEPTHOUT_LESS_EQUAL = 0x27,
VKD3D_SM5_RT_OUTPUT_STENCIL_REF = 0x29,
};
enum vkd3d_sm4_extended_operand_type
{
VKD3D_SM4_EXTENDED_OPERAND_NONE = 0x0,
VKD3D_SM4_EXTENDED_OPERAND_MODIFIER = 0x1,
};
enum vkd3d_sm4_register_modifier
{
VKD3D_SM4_REGISTER_MODIFIER_NONE = 0x00,
VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x01,
VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x02,
VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0x03,
};
enum vkd3d_sm4_register_precision
{
VKD3D_SM4_REGISTER_PRECISION_DEFAULT = 0x0,
VKD3D_SM4_REGISTER_PRECISION_MIN_FLOAT_16 = 0x1,
VKD3D_SM4_REGISTER_PRECISION_MIN_FLOAT_10 = 0x2,
VKD3D_SM4_REGISTER_PRECISION_MIN_INT_16 = 0x4,
VKD3D_SM4_REGISTER_PRECISION_MIN_UINT_16 = 0x5,
};
enum vkd3d_sm4_output_primitive_type
{
VKD3D_SM4_OUTPUT_PT_POINTLIST = 0x1,
VKD3D_SM4_OUTPUT_PT_LINESTRIP = 0x3,
VKD3D_SM4_OUTPUT_PT_TRIANGLESTRIP = 0x5,
};
enum vkd3d_sm4_input_primitive_type
{
VKD3D_SM4_INPUT_PT_POINT = 0x01,
VKD3D_SM4_INPUT_PT_LINE = 0x02,
VKD3D_SM4_INPUT_PT_TRIANGLE = 0x03,
VKD3D_SM4_INPUT_PT_LINEADJ = 0x06,
VKD3D_SM4_INPUT_PT_TRIANGLEADJ = 0x07,
VKD3D_SM5_INPUT_PT_PATCH1 = 0x08,
VKD3D_SM5_INPUT_PT_PATCH2 = 0x09,
VKD3D_SM5_INPUT_PT_PATCH3 = 0x0a,
VKD3D_SM5_INPUT_PT_PATCH4 = 0x0b,
VKD3D_SM5_INPUT_PT_PATCH5 = 0x0c,
VKD3D_SM5_INPUT_PT_PATCH6 = 0x0d,
VKD3D_SM5_INPUT_PT_PATCH7 = 0x0e,
VKD3D_SM5_INPUT_PT_PATCH8 = 0x0f,
VKD3D_SM5_INPUT_PT_PATCH9 = 0x10,
VKD3D_SM5_INPUT_PT_PATCH10 = 0x11,
VKD3D_SM5_INPUT_PT_PATCH11 = 0x12,
VKD3D_SM5_INPUT_PT_PATCH12 = 0x13,
VKD3D_SM5_INPUT_PT_PATCH13 = 0x14,
VKD3D_SM5_INPUT_PT_PATCH14 = 0x15,
VKD3D_SM5_INPUT_PT_PATCH15 = 0x16,
VKD3D_SM5_INPUT_PT_PATCH16 = 0x17,
VKD3D_SM5_INPUT_PT_PATCH17 = 0x18,
VKD3D_SM5_INPUT_PT_PATCH18 = 0x19,
VKD3D_SM5_INPUT_PT_PATCH19 = 0x1a,
VKD3D_SM5_INPUT_PT_PATCH20 = 0x1b,
VKD3D_SM5_INPUT_PT_PATCH21 = 0x1c,
VKD3D_SM5_INPUT_PT_PATCH22 = 0x1d,
VKD3D_SM5_INPUT_PT_PATCH23 = 0x1e,
VKD3D_SM5_INPUT_PT_PATCH24 = 0x1f,
VKD3D_SM5_INPUT_PT_PATCH25 = 0x20,
VKD3D_SM5_INPUT_PT_PATCH26 = 0x21,
VKD3D_SM5_INPUT_PT_PATCH27 = 0x22,
VKD3D_SM5_INPUT_PT_PATCH28 = 0x23,
VKD3D_SM5_INPUT_PT_PATCH29 = 0x24,
VKD3D_SM5_INPUT_PT_PATCH30 = 0x25,
VKD3D_SM5_INPUT_PT_PATCH31 = 0x26,
VKD3D_SM5_INPUT_PT_PATCH32 = 0x27,
};
enum vkd3d_sm4_swizzle_type
{
VKD3D_SM4_SWIZZLE_NONE = 0x0,
VKD3D_SM4_SWIZZLE_VEC4 = 0x1,
VKD3D_SM4_SWIZZLE_SCALAR = 0x2,
};
enum vkd3d_sm4_dimension
{
VKD3D_SM4_DIMENSION_NONE = 0x0,
VKD3D_SM4_DIMENSION_SCALAR = 0x1,
VKD3D_SM4_DIMENSION_VEC4 = 0x2,
};
enum vkd3d_sm4_resource_type
{
VKD3D_SM4_RESOURCE_BUFFER = 0x1,
VKD3D_SM4_RESOURCE_TEXTURE_1D = 0x2,
VKD3D_SM4_RESOURCE_TEXTURE_2D = 0x3,
VKD3D_SM4_RESOURCE_TEXTURE_2DMS = 0x4,
VKD3D_SM4_RESOURCE_TEXTURE_3D = 0x5,
VKD3D_SM4_RESOURCE_TEXTURE_CUBE = 0x6,
VKD3D_SM4_RESOURCE_TEXTURE_1DARRAY = 0x7,
VKD3D_SM4_RESOURCE_TEXTURE_2DARRAY = 0x8,
VKD3D_SM4_RESOURCE_TEXTURE_2DMSARRAY = 0x9,
VKD3D_SM4_RESOURCE_TEXTURE_CUBEARRAY = 0xa,
VKD3D_SM4_RESOURCE_RAW_BUFFER = 0xb,
VKD3D_SM4_RESOURCE_STRUCTURED_BUFFER = 0xc,
};
enum vkd3d_sm4_data_type
{
VKD3D_SM4_DATA_UNORM = 0x1,
VKD3D_SM4_DATA_SNORM = 0x2,
VKD3D_SM4_DATA_INT = 0x3,
VKD3D_SM4_DATA_UINT = 0x4,
VKD3D_SM4_DATA_FLOAT = 0x5,
VKD3D_SM4_DATA_MIXED = 0x6,
VKD3D_SM4_DATA_DOUBLE = 0x7,
VKD3D_SM4_DATA_CONTINUED = 0x8,
VKD3D_SM4_DATA_UNUSED = 0x9,
};
enum vkd3d_sm4_sampler_mode
{
VKD3D_SM4_SAMPLER_DEFAULT = 0x0,
VKD3D_SM4_SAMPLER_COMPARISON = 0x1,
};
enum vkd3d_sm4_shader_data_type
{
VKD3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER = 0x3,
VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
};
#endif /* __VKD3D_SM4_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,512 @@
/*
* Copyright 2016-2017 Józef Kucia 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_private.h"
VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG");
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
REFIID iid, void **device)
{
struct vkd3d_instance *instance;
struct d3d12_device *object;
HRESULT hr;
TRACE("create_info %p, iid %s, device %p.\n", create_info, debugstr_guid(iid), device);
if (!create_info)
return E_INVALIDARG;
if (create_info->type != VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
{
WARN("Invalid structure type %#x.\n", create_info->type);
return E_INVALIDARG;
}
if (!create_info->instance && !create_info->instance_create_info)
{
ERR("Instance or instance create info is required.\n");
return E_INVALIDARG;
}
if (create_info->instance && create_info->instance_create_info)
{
ERR("Instance and instance create info are mutually exclusive parameters.\n");
return E_INVALIDARG;
}
if (create_info->minimum_feature_level < D3D_FEATURE_LEVEL_11_0
|| !is_valid_feature_level(create_info->minimum_feature_level))
{
WARN("Invalid feature level %#x.\n", create_info->minimum_feature_level);
return E_INVALIDARG;
}
if ((instance = create_info->instance))
{
vkd3d_instance_incref(instance);
}
else if (FAILED(hr = vkd3d_create_instance(create_info->instance_create_info, &instance)))
{
WARN("Failed to create instance, hr %#x.\n", hr);
return E_FAIL;
}
hr = d3d12_device_create(instance, create_info, &object);
vkd3d_instance_decref(instance);
if (FAILED(hr))
return hr;
if (!device)
{
ID3D12Device_Release(&object->ID3D12Device_iface);
return S_FALSE;
}
return return_interface(&object->ID3D12Device_iface, &IID_ID3D12Device, iid, device);
}
/* ID3D12RootSignatureDeserializer */
struct d3d12_root_signature_deserializer
{
ID3D12RootSignatureDeserializer ID3D12RootSignatureDeserializer_iface;
LONG refcount;
union
{
D3D12_VERSIONED_ROOT_SIGNATURE_DESC d3d12;
struct vkd3d_shader_versioned_root_signature_desc vkd3d;
} desc;
};
STATIC_ASSERT(sizeof(D3D12_ROOT_SIGNATURE_DESC) == sizeof(struct vkd3d_shader_root_signature_desc));
static struct d3d12_root_signature_deserializer *impl_from_ID3D12RootSignatureDeserializer(
ID3D12RootSignatureDeserializer *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_root_signature_deserializer, ID3D12RootSignatureDeserializer_iface);
}
static HRESULT STDMETHODCALLTYPE d3d12_root_signature_deserializer_QueryInterface(
ID3D12RootSignatureDeserializer *iface, REFIID riid, void **object)
{
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
/* QueryInterface() implementation is broken, E_NOINTERFACE is returned for
* IUnknown.
*/
if (IsEqualGUID(riid, &IID_ID3D12RootSignatureDeserializer))
{
ID3D12RootSignatureDeserializer_AddRef(iface);
*object = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
*object = NULL;
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_AddRef(ID3D12RootSignatureDeserializer *iface)
{
struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
ULONG refcount = InterlockedIncrement(&deserializer->refcount);
TRACE("%p increasing refcount to %u.\n", deserializer, refcount);
return refcount;
}
static ULONG STDMETHODCALLTYPE d3d12_root_signature_deserializer_Release(ID3D12RootSignatureDeserializer *iface)
{
struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
ULONG refcount = InterlockedDecrement(&deserializer->refcount);
TRACE("%p decreasing refcount to %u.\n", deserializer, refcount);
if (!refcount)
{
vkd3d_shader_free_root_signature(&deserializer->desc.vkd3d);
vkd3d_free(deserializer);
}
return refcount;
}
static const D3D12_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE d3d12_root_signature_deserializer_GetRootSignatureDesc(
ID3D12RootSignatureDeserializer *iface)
{
struct d3d12_root_signature_deserializer *deserializer = impl_from_ID3D12RootSignatureDeserializer(iface);
TRACE("iface %p.\n", iface);
assert(deserializer->desc.d3d12.Version == D3D_ROOT_SIGNATURE_VERSION_1_0);
return &deserializer->desc.d3d12.u.Desc_1_0;
}
static const struct ID3D12RootSignatureDeserializerVtbl d3d12_root_signature_deserializer_vtbl =
{
/* IUnknown methods */
d3d12_root_signature_deserializer_QueryInterface,
d3d12_root_signature_deserializer_AddRef,
d3d12_root_signature_deserializer_Release,
/* ID3D12RootSignatureDeserializer methods */
d3d12_root_signature_deserializer_GetRootSignatureDesc,
};
int vkd3d_parse_root_signature_v_1_0(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_versioned_root_signature_desc *out_desc)
{
struct vkd3d_shader_versioned_root_signature_desc desc, converted_desc;
int ret;
if ((ret = vkd3d_shader_parse_root_signature(dxbc, &desc, NULL)) < 0)
{
WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
return ret;
}
if (desc.version == VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0)
{
*out_desc = desc;
}
else
{
enum vkd3d_shader_root_signature_version version = desc.version;
ret = vkd3d_shader_convert_root_signature(&converted_desc, VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0, &desc);
vkd3d_shader_free_root_signature(&desc);
if (ret < 0)
{
WARN("Failed to convert from version %#x, vkd3d result %d.\n", version, ret);
return ret;
}
*out_desc = converted_desc;
}
return ret;
}
static HRESULT d3d12_root_signature_deserializer_init(struct d3d12_root_signature_deserializer *deserializer,
const struct vkd3d_shader_code *dxbc)
{
int ret;
deserializer->ID3D12RootSignatureDeserializer_iface.lpVtbl = &d3d12_root_signature_deserializer_vtbl;
deserializer->refcount = 1;
if ((ret = vkd3d_parse_root_signature_v_1_0(dxbc, &deserializer->desc.vkd3d)) < 0)
return hresult_from_vkd3d_result(ret);
return S_OK;
}
HRESULT vkd3d_create_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer)
{
struct vkd3d_shader_code dxbc = {data, data_size};
struct d3d12_root_signature_deserializer *object;
HRESULT hr;
TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
data, data_size, debugstr_guid(iid), deserializer);
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
if (FAILED(hr = d3d12_root_signature_deserializer_init(object, &dxbc)))
{
vkd3d_free(object);
return hr;
}
return return_interface(&object->ID3D12RootSignatureDeserializer_iface,
&IID_ID3D12RootSignatureDeserializer, iid, deserializer);
}
/* ID3D12VersionedRootSignatureDeserializer */
struct d3d12_versioned_root_signature_deserializer
{
ID3D12VersionedRootSignatureDeserializer ID3D12VersionedRootSignatureDeserializer_iface;
LONG refcount;
union
{
D3D12_VERSIONED_ROOT_SIGNATURE_DESC d3d12;
struct vkd3d_shader_versioned_root_signature_desc vkd3d;
} desc, other_desc;
};
STATIC_ASSERT(sizeof(D3D12_VERSIONED_ROOT_SIGNATURE_DESC) == sizeof(struct vkd3d_shader_versioned_root_signature_desc));
static struct d3d12_versioned_root_signature_deserializer *impl_from_ID3D12VersionedRootSignatureDeserializer(
ID3D12VersionedRootSignatureDeserializer *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_versioned_root_signature_deserializer,
ID3D12VersionedRootSignatureDeserializer_iface);
}
static HRESULT STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_QueryInterface(
ID3D12VersionedRootSignatureDeserializer *iface, REFIID iid, void **object)
{
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
/* QueryInterface() implementation is broken, E_NOINTERFACE is returned for
* IUnknown.
*/
if (IsEqualGUID(iid, &IID_ID3D12VersionedRootSignatureDeserializer))
{
ID3D12VersionedRootSignatureDeserializer_AddRef(iface);
*object = iface;
return S_OK;
}
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
*object = NULL;
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_AddRef(ID3D12VersionedRootSignatureDeserializer *iface)
{
struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
ULONG refcount = InterlockedIncrement(&deserializer->refcount);
TRACE("%p increasing refcount to %u.\n", deserializer, refcount);
return refcount;
}
static ULONG STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_Release(ID3D12VersionedRootSignatureDeserializer *iface)
{
struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
ULONG refcount = InterlockedDecrement(&deserializer->refcount);
TRACE("%p decreasing refcount to %u.\n", deserializer, refcount);
if (!refcount)
{
vkd3d_shader_free_root_signature(&deserializer->desc.vkd3d);
vkd3d_shader_free_root_signature(&deserializer->other_desc.vkd3d);
vkd3d_free(deserializer);
}
return refcount;
}
static enum vkd3d_shader_root_signature_version vkd3d_root_signature_version_from_d3d12(
D3D_ROOT_SIGNATURE_VERSION version)
{
switch (version)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
return VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0;
case D3D_ROOT_SIGNATURE_VERSION_1_1:
return VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_1;
default:
WARN("Unknown root signature version %#x.\n", version);
return 0;
}
}
static HRESULT STDMETHODCALLTYPE d3d12_versioned_root_signature_deserializer_GetRootSignatureDescAtVersion(
ID3D12VersionedRootSignatureDeserializer *iface, D3D_ROOT_SIGNATURE_VERSION version,
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC **desc)
{
struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
int ret;
TRACE("iface %p, version %#x, desc %p.\n", iface, version, desc);
if (version != D3D_ROOT_SIGNATURE_VERSION_1_0 && version != D3D_ROOT_SIGNATURE_VERSION_1_1)
{
WARN("Root signature version %#x not supported.\n", version);
return E_INVALIDARG;
}
if (deserializer->desc.d3d12.Version == version)
{
*desc = &deserializer->desc.d3d12;
return S_OK;
}
if (!deserializer->other_desc.d3d12.Version)
{
if ((ret = vkd3d_shader_convert_root_signature(&deserializer->other_desc.vkd3d,
vkd3d_root_signature_version_from_d3d12(version), &deserializer->desc.vkd3d)) < 0)
{
WARN("Failed to convert versioned root signature, vkd3d result %d.\n", ret);
return hresult_from_vkd3d_result(ret);
}
}
assert(deserializer->other_desc.d3d12.Version == version);
*desc = &deserializer->other_desc.d3d12;
return S_OK;
}
static const D3D12_VERSIONED_ROOT_SIGNATURE_DESC * STDMETHODCALLTYPE
d3d12_versioned_root_signature_deserializer_GetUnconvertedRootSignatureDesc(ID3D12VersionedRootSignatureDeserializer *iface)
{
struct d3d12_versioned_root_signature_deserializer *deserializer = impl_from_ID3D12VersionedRootSignatureDeserializer(iface);
TRACE("iface %p.\n", iface);
return &deserializer->desc.d3d12;
}
static const struct ID3D12VersionedRootSignatureDeserializerVtbl d3d12_versioned_root_signature_deserializer_vtbl =
{
/* IUnknown methods */
d3d12_versioned_root_signature_deserializer_QueryInterface,
d3d12_versioned_root_signature_deserializer_AddRef,
d3d12_versioned_root_signature_deserializer_Release,
/* ID3D12VersionedRootSignatureDeserializer methods */
d3d12_versioned_root_signature_deserializer_GetRootSignatureDescAtVersion,
d3d12_versioned_root_signature_deserializer_GetUnconvertedRootSignatureDesc,
};
static HRESULT d3d12_versioned_root_signature_deserializer_init(struct d3d12_versioned_root_signature_deserializer *deserializer,
const struct vkd3d_shader_code *dxbc)
{
int ret;
deserializer->ID3D12VersionedRootSignatureDeserializer_iface.lpVtbl = &d3d12_versioned_root_signature_deserializer_vtbl;
deserializer->refcount = 1;
if ((ret = vkd3d_shader_parse_root_signature(dxbc, &deserializer->desc.vkd3d, NULL)) < 0)
{
WARN("Failed to parse root signature, vkd3d result %d.\n", ret);
return hresult_from_vkd3d_result(ret);
}
memset(&deserializer->other_desc, 0, sizeof(deserializer->other_desc));
return S_OK;
}
HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZE_T data_size,
REFIID iid, void **deserializer)
{
struct d3d12_versioned_root_signature_deserializer *object;
struct vkd3d_shader_code dxbc = {data, data_size};
HRESULT hr;
TRACE("data %p, data_size %lu, iid %s, deserializer %p.\n",
data, data_size, debugstr_guid(iid), deserializer);
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
if (FAILED(hr = d3d12_versioned_root_signature_deserializer_init(object, &dxbc)))
{
vkd3d_free(object);
return hr;
}
return return_interface(&object->ID3D12VersionedRootSignatureDeserializer_iface,
&IID_ID3D12VersionedRootSignatureDeserializer, iid, deserializer);
}
HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *desc,
D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob)
{
struct vkd3d_shader_versioned_root_signature_desc vkd3d_desc;
struct vkd3d_shader_code dxbc;
char *messages;
HRESULT hr;
int ret;
TRACE("desc %p, version %#x, blob %p, error_blob %p.\n", desc, version, blob, error_blob);
if (version != D3D_ROOT_SIGNATURE_VERSION_1_0)
{
WARN("Unexpected Root signature version %#x.\n", version);
return E_INVALIDARG;
}
if (!blob)
{
WARN("Invalid blob parameter.\n");
return E_INVALIDARG;
}
if (error_blob)
*error_blob = NULL;
vkd3d_desc.version = VKD3D_SHADER_ROOT_SIGNATURE_VERSION_1_0;
vkd3d_desc.u.v_1_0 = *(const struct vkd3d_shader_root_signature_desc *)desc;
if ((ret = vkd3d_shader_serialize_root_signature(&vkd3d_desc, &dxbc, &messages)) < 0)
{
WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
if (error_blob && messages)
{
if (FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob)))
ERR("Failed to create error blob, hr %#x.\n", hr);
}
return hresult_from_vkd3d_result(ret);
}
vkd3d_shader_free_messages(messages);
if (FAILED(hr = vkd3d_blob_create((void *)dxbc.code, dxbc.size, blob)))
{
WARN("Failed to create blob object, hr %#x.\n", hr);
vkd3d_shader_free_shader_code(&dxbc);
}
return hr;
}
HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *desc,
ID3DBlob **blob, ID3DBlob **error_blob)
{
const struct vkd3d_shader_versioned_root_signature_desc *vkd3d_desc;
struct vkd3d_shader_code dxbc;
char *messages;
HRESULT hr;
int ret;
TRACE("desc %p, blob %p, error_blob %p.\n", desc, blob, error_blob);
if (!blob)
{
WARN("Invalid blob parameter.\n");
return E_INVALIDARG;
}
if (error_blob)
*error_blob = NULL;
vkd3d_desc = (const struct vkd3d_shader_versioned_root_signature_desc *)desc;
if ((ret = vkd3d_shader_serialize_root_signature(vkd3d_desc, &dxbc, &messages)) < 0)
{
WARN("Failed to serialize root signature, vkd3d result %d.\n", ret);
if (error_blob && messages)
{
if (FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob)))
ERR("Failed to create error blob, hr %#x.\n", hr);
}
return hresult_from_vkd3d_result(ret);
}
vkd3d_shader_free_messages(messages);
if (FAILED(hr = vkd3d_blob_create((void *)dxbc.code, dxbc.size, blob)))
{
WARN("Failed to create blob object, hr %#x.\n", hr);
vkd3d_shader_free_shader_code(&dxbc);
}
return hr;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,388 @@
/*
* Copyright 2019 Philip Rebohle
*
* 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_SHADERS_H
#define __VKD3D_SHADERS_H
static const uint32_t cs_uav_clear_buffer_float_code[] =
{
#if 0
RWBuffer<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(128, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
}
#endif
0x43425844, 0xe114ba61, 0xff6a0d0b, 0x7b25c8f4, 0xfcf7cf22, 0x00000001, 0x0000010c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_buffer_uint_code[] =
{
#if 0
RWBuffer<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(128, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
}
#endif
0x43425844, 0x3afd0cfd, 0x5145c166, 0x5b9f76b8, 0xa73775cd, 0x00000001, 0x0000010c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_1d_array_float_code[] =
{
#if 0
RWTexture1DArray<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(64, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
}
#endif
0x43425844, 0x3d73bc2d, 0x2b635f3d, 0x6bf98e92, 0xbe0aa5d9, 0x00000001, 0x0000011c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_1d_array_uint_code[] =
{
#if 0
RWTexture1DArray<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(64, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
}
#endif
0x43425844, 0x2f0ca457, 0x72068b34, 0xd9dadc2b, 0xd3178c3e, 0x00000001, 0x0000011c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_1d_float_code[] =
{
#if 0
RWTexture1D<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(64, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
}
#endif
0x43425844, 0x05266503, 0x4b97006f, 0x01a5cc63, 0xe617d0a1, 0x00000001, 0x0000010c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_1d_uint_code[] =
{
#if 0
RWTexture1D<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(64, 1, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (thread_id.x < u_info.dst_extent.x)
dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
}
#endif
0x43425844, 0x19d5c8f2, 0x3ca4ac24, 0x9e258499, 0xf0463fd6, 0x00000001, 0x0000010c, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_2d_array_float_code[] =
{
#if 0
RWTexture2DArray<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
}
#endif
0x43425844, 0x924d2d2c, 0xb9166376, 0x99f83871, 0x8ef65025, 0x00000001, 0x00000138, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_2d_array_uint_code[] =
{
#if 0
RWTexture2DArray<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
}
#endif
0x43425844, 0xa92219d4, 0xa2c5e47d, 0x0d308500, 0xf32197b4, 0x00000001, 0x00000138, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_2d_float_code[] =
{
#if 0
RWTexture2D<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
}
#endif
0x43425844, 0x6e735b3f, 0x7348c4fa, 0xb3634e42, 0x50e2d99b, 0x00000001, 0x00000128, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_2d_uint_code[] =
{
#if 0
RWTexture2D<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
}
#endif
0x43425844, 0xf01db5dd, 0xc7dc5e55, 0xb017c1a8, 0x55abd52d, 0x00000001, 0x00000128, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_3d_float_code[] =
{
#if 0
RWTexture3D<float4> dst;
struct
{
float4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
}
#endif
0x43425844, 0x5d8f36a0, 0x30fa86a5, 0xfec7f2ef, 0xdfd76cbb, 0x00000001, 0x00000138, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00005555,
0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
static const uint32_t cs_uav_clear_3d_uint_code[] =
{
#if 0
RWTexture3D<uint4> dst;
struct
{
uint4 clear_value;
int2 dst_offset;
int2 dst_extent;
} u_info;
[numthreads(8, 8, 1)]
void main(int3 thread_id : SV_DispatchThreadID)
{
if (all(thread_id.xy < u_info.dst_extent.xy))
dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
}
#endif
0x43425844, 0x5b9c95b1, 0xc9bde4e3, 0x9aaff806, 0x24a1d264, 0x00000001, 0x00000138, 0x00000003,
0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00004444,
0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
};
#endif /* __VKD3D_SHADERS_H */

View File

@ -0,0 +1,218 @@
/*
* Copyright 2016 Józef Kucia 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 VK_INSTANCE_PFN
# define VK_INSTANCE_PFN(x)
#endif
#ifndef VK_INSTANCE_EXT_PFN
# define VK_INSTANCE_EXT_PFN(x)
#endif
#ifndef VK_DEVICE_PFN
# define VK_DEVICE_PFN(x)
#endif
#ifndef VK_DEVICE_EXT_PFN
# define VK_DEVICE_EXT_PFN(x)
#endif
/* Instance functions (obtained by vkGetInstanceProcAddr). */
VK_INSTANCE_PFN(vkDestroyInstance) /* Load vkDestroyInstance() first. */
VK_INSTANCE_PFN(vkCreateDevice)
VK_INSTANCE_PFN(vkEnumerateDeviceExtensionProperties)
VK_INSTANCE_PFN(vkEnumerateDeviceLayerProperties)
VK_INSTANCE_PFN(vkEnumeratePhysicalDevices)
VK_INSTANCE_PFN(vkGetDeviceProcAddr)
VK_INSTANCE_PFN(vkGetPhysicalDeviceFeatures)
VK_INSTANCE_PFN(vkGetPhysicalDeviceFormatProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceImageFormatProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceMemoryProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceQueueFamilyProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties)
/* VK_KHR_get_physical_device_properties2 */
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceFeatures2KHR)
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2KHR)
/* VK_EXT_debug_report */
VK_INSTANCE_EXT_PFN(vkCreateDebugReportCallbackEXT)
VK_INSTANCE_EXT_PFN(vkDestroyDebugReportCallbackEXT)
/* VK_EXT_calibrated_timestamps */
VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)
/* Device functions (obtained by vkGetDeviceProcAddr). */
VK_DEVICE_PFN(vkDestroyDevice) /* Load vkDestroyDevice() first. */
VK_DEVICE_PFN(vkAllocateCommandBuffers)
VK_DEVICE_PFN(vkAllocateDescriptorSets)
VK_DEVICE_PFN(vkAllocateMemory)
VK_DEVICE_PFN(vkBeginCommandBuffer)
VK_DEVICE_PFN(vkBindBufferMemory)
VK_DEVICE_PFN(vkBindImageMemory)
VK_DEVICE_PFN(vkCmdBeginQuery)
VK_DEVICE_PFN(vkCmdBeginRenderPass)
VK_DEVICE_PFN(vkCmdBindDescriptorSets)
VK_DEVICE_PFN(vkCmdBindIndexBuffer)
VK_DEVICE_PFN(vkCmdBindPipeline)
VK_DEVICE_PFN(vkCmdBindVertexBuffers)
VK_DEVICE_PFN(vkCmdBlitImage)
VK_DEVICE_PFN(vkCmdClearAttachments)
VK_DEVICE_PFN(vkCmdClearColorImage)
VK_DEVICE_PFN(vkCmdClearDepthStencilImage)
VK_DEVICE_PFN(vkCmdCopyBuffer)
VK_DEVICE_PFN(vkCmdCopyBufferToImage)
VK_DEVICE_PFN(vkCmdCopyImage)
VK_DEVICE_PFN(vkCmdCopyImageToBuffer)
VK_DEVICE_PFN(vkCmdCopyQueryPoolResults)
VK_DEVICE_PFN(vkCmdDispatch)
VK_DEVICE_PFN(vkCmdDispatchIndirect)
VK_DEVICE_PFN(vkCmdDraw)
VK_DEVICE_PFN(vkCmdDrawIndexed)
VK_DEVICE_PFN(vkCmdDrawIndexedIndirect)
VK_DEVICE_PFN(vkCmdDrawIndirect)
VK_DEVICE_PFN(vkCmdEndQuery)
VK_DEVICE_PFN(vkCmdEndRenderPass)
VK_DEVICE_PFN(vkCmdExecuteCommands)
VK_DEVICE_PFN(vkCmdFillBuffer)
VK_DEVICE_PFN(vkCmdNextSubpass)
VK_DEVICE_PFN(vkCmdPipelineBarrier)
VK_DEVICE_PFN(vkCmdPushConstants)
VK_DEVICE_PFN(vkCmdResetEvent)
VK_DEVICE_PFN(vkCmdResetQueryPool)
VK_DEVICE_PFN(vkCmdResolveImage)
VK_DEVICE_PFN(vkCmdSetBlendConstants)
VK_DEVICE_PFN(vkCmdSetDepthBias)
VK_DEVICE_PFN(vkCmdSetDepthBounds)
VK_DEVICE_PFN(vkCmdSetEvent)
VK_DEVICE_PFN(vkCmdSetLineWidth)
VK_DEVICE_PFN(vkCmdSetScissor)
VK_DEVICE_PFN(vkCmdSetStencilCompareMask)
VK_DEVICE_PFN(vkCmdSetStencilReference)
VK_DEVICE_PFN(vkCmdSetStencilWriteMask)
VK_DEVICE_PFN(vkCmdSetViewport)
VK_DEVICE_PFN(vkCmdUpdateBuffer)
VK_DEVICE_PFN(vkCmdWaitEvents)
VK_DEVICE_PFN(vkCmdWriteTimestamp)
VK_DEVICE_PFN(vkCreateBuffer)
VK_DEVICE_PFN(vkCreateBufferView)
VK_DEVICE_PFN(vkCreateCommandPool)
VK_DEVICE_PFN(vkCreateComputePipelines)
VK_DEVICE_PFN(vkCreateDescriptorPool)
VK_DEVICE_PFN(vkCreateDescriptorSetLayout)
VK_DEVICE_PFN(vkCreateEvent)
VK_DEVICE_PFN(vkCreateFence)
VK_DEVICE_PFN(vkCreateFramebuffer)
VK_DEVICE_PFN(vkCreateGraphicsPipelines)
VK_DEVICE_PFN(vkCreateImage)
VK_DEVICE_PFN(vkCreateImageView)
VK_DEVICE_PFN(vkCreatePipelineCache)
VK_DEVICE_PFN(vkCreatePipelineLayout)
VK_DEVICE_PFN(vkCreateQueryPool)
VK_DEVICE_PFN(vkCreateRenderPass)
VK_DEVICE_PFN(vkCreateSampler)
VK_DEVICE_PFN(vkCreateSemaphore)
VK_DEVICE_PFN(vkCreateShaderModule)
VK_DEVICE_PFN(vkDestroyBuffer)
VK_DEVICE_PFN(vkDestroyBufferView)
VK_DEVICE_PFN(vkDestroyCommandPool)
VK_DEVICE_PFN(vkDestroyDescriptorPool)
VK_DEVICE_PFN(vkDestroyDescriptorSetLayout)
VK_DEVICE_PFN(vkDestroyEvent)
VK_DEVICE_PFN(vkDestroyFence)
VK_DEVICE_PFN(vkDestroyFramebuffer)
VK_DEVICE_PFN(vkDestroyImage)
VK_DEVICE_PFN(vkDestroyImageView)
VK_DEVICE_PFN(vkDestroyPipeline)
VK_DEVICE_PFN(vkDestroyPipelineCache)
VK_DEVICE_PFN(vkDestroyPipelineLayout)
VK_DEVICE_PFN(vkDestroyQueryPool)
VK_DEVICE_PFN(vkDestroyRenderPass)
VK_DEVICE_PFN(vkDestroySampler)
VK_DEVICE_PFN(vkDestroySemaphore)
VK_DEVICE_PFN(vkDestroyShaderModule)
VK_DEVICE_PFN(vkDeviceWaitIdle)
VK_DEVICE_PFN(vkEndCommandBuffer)
VK_DEVICE_PFN(vkFlushMappedMemoryRanges)
VK_DEVICE_PFN(vkFreeCommandBuffers)
VK_DEVICE_PFN(vkFreeDescriptorSets)
VK_DEVICE_PFN(vkFreeMemory)
VK_DEVICE_PFN(vkGetBufferMemoryRequirements)
VK_DEVICE_PFN(vkGetDeviceMemoryCommitment)
VK_DEVICE_PFN(vkGetDeviceQueue)
VK_DEVICE_PFN(vkGetEventStatus)
VK_DEVICE_PFN(vkGetFenceStatus)
VK_DEVICE_PFN(vkGetImageMemoryRequirements)
VK_DEVICE_PFN(vkGetImageSparseMemoryRequirements)
VK_DEVICE_PFN(vkGetImageSubresourceLayout)
VK_DEVICE_PFN(vkGetPipelineCacheData)
VK_DEVICE_PFN(vkGetQueryPoolResults)
VK_DEVICE_PFN(vkGetRenderAreaGranularity)
VK_DEVICE_PFN(vkInvalidateMappedMemoryRanges)
VK_DEVICE_PFN(vkMapMemory)
VK_DEVICE_PFN(vkMergePipelineCaches)
VK_DEVICE_PFN(vkQueueBindSparse)
VK_DEVICE_PFN(vkQueueSubmit)
VK_DEVICE_PFN(vkQueueWaitIdle)
VK_DEVICE_PFN(vkResetCommandBuffer)
VK_DEVICE_PFN(vkResetCommandPool)
VK_DEVICE_PFN(vkResetDescriptorPool)
VK_DEVICE_PFN(vkResetEvent)
VK_DEVICE_PFN(vkResetFences)
VK_DEVICE_PFN(vkSetEvent)
VK_DEVICE_PFN(vkUnmapMemory)
VK_DEVICE_PFN(vkUpdateDescriptorSets)
VK_DEVICE_PFN(vkWaitForFences)
/* VK_KHR_draw_indirect_count */
VK_DEVICE_EXT_PFN(vkCmdDrawIndirectCountKHR)
VK_DEVICE_EXT_PFN(vkCmdDrawIndexedIndirectCountKHR)
/* VK_KHR_get_memory_requirements2 */
VK_DEVICE_EXT_PFN(vkGetBufferMemoryRequirements2KHR)
VK_DEVICE_EXT_PFN(vkGetImageMemoryRequirements2KHR)
VK_DEVICE_EXT_PFN(vkGetImageSparseMemoryRequirements2KHR)
/* VK_KHR_maintenance3 */
VK_DEVICE_EXT_PFN(vkGetDescriptorSetLayoutSupportKHR)
/* VK_KHR_push_descriptor */
VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR)
/* VK_EXT_calibrated_timestamps */
VK_DEVICE_EXT_PFN(vkGetCalibratedTimestampsEXT)
/* VK_EXT_conditional_rendering */
VK_DEVICE_EXT_PFN(vkCmdBeginConditionalRenderingEXT)
VK_DEVICE_EXT_PFN(vkCmdEndConditionalRenderingEXT)
/* VK_EXT_debug_marker */
VK_DEVICE_EXT_PFN(vkDebugMarkerSetObjectNameEXT)
/* VK_EXT_transform_feedback */
VK_DEVICE_EXT_PFN(vkCmdBeginQueryIndexedEXT)
VK_DEVICE_EXT_PFN(vkCmdBeginTransformFeedbackEXT)
VK_DEVICE_EXT_PFN(vkCmdBindTransformFeedbackBuffersEXT)
VK_DEVICE_EXT_PFN(vkCmdEndQueryIndexedEXT)
VK_DEVICE_EXT_PFN(vkCmdEndTransformFeedbackEXT)
#undef VK_INSTANCE_PFN
#undef VK_INSTANCE_EXT_PFN
#undef VK_DEVICE_PFN
#undef VK_DEVICE_EXT_PFN