1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

vkd3d: Import upstream release 1.12.

This commit is contained in:
Alexandre Julliard 2024-05-29 22:54:58 +02:00
parent 8d587a47eb
commit fecd22d2ae
39 changed files with 12000 additions and 3438 deletions

View File

@ -9941,7 +9941,6 @@ static void test_effect_compiler(void)
cb = effect->lpVtbl->GetConstantBufferByIndex(effect, 1);
hr = cb->lpVtbl->GetDesc(cb, &var_desc);
todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
if (hr == S_OK)
ok(!strcmp(var_desc.Name, "cb1"), "Unexpected variable name %s.\n", var_desc.Name);

View File

@ -586,7 +586,7 @@ static void test_conditionals(void)
ID3D10Blob_Release(ps_code);
}
todo_wine ps_code = compile_shader(ps_ternary_source, "ps_2_0", 0);
ps_code = compile_shader(ps_ternary_source, "ps_2_0", 0);
if (ps_code)
{
draw_quad(device, ps_code);
@ -595,7 +595,6 @@ static void test_conditionals(void)
for (i = 0; i < 320; i += 40)
{
v = get_readback_vec4(&rb, i, 0);
todo_wine
ok(compare_vec4(v, 0.5f, 0.25f, 0.5f, 0.75f, 0),
"Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
}
@ -603,7 +602,6 @@ static void test_conditionals(void)
for (i = 360; i < 640; i += 40)
{
v = get_readback_vec4(&rb, i, 0);
todo_wine
ok(compare_vec4(v, 0.6f, 0.8f, 0.1f, 0.2f, 0),
"Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v->x, v->y, v->z, v->w);
}
@ -662,7 +660,6 @@ static void test_float_vectors(void)
ID3D10Blob_Release(ps_code);
}
todo_wine
ps_code = compile_shader(ps_uniform_indexing_source, "ps_2_0", 0);
if (ps_code)
{
@ -674,7 +671,6 @@ static void test_float_vectors(void)
draw_quad(device, ps_code);
v = get_color_vec4(device, 0, 0);
todo_wine
ok(compare_vec4(&v, 0.5f, 0.3f, 0.8f, 0.2f, 0),
"Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);

View File

@ -10,6 +10,7 @@ Chip Davis
Conor McCarthy
David Gow
Derek Lesho
Elizabeth Figura
Ethan Lee
Evan Tang
Fabian Maurer
@ -36,5 +37,4 @@ Stefan Dösinger
Sven Hesse
Victor Chiletto
Vinson Lee
Zebediah Figura
Zhiyi Zhang

View File

@ -30,6 +30,7 @@ SOURCES = \
libs/vkd3d-shader/spirv.c \
libs/vkd3d-shader/tpf.c \
libs/vkd3d-shader/vkd3d_shader_main.c \
libs/vkd3d/cache.c \
libs/vkd3d/command.c \
libs/vkd3d/device.c \
libs/vkd3d/resource.c \

View File

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

View File

@ -30,6 +30,9 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <pthread.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
@ -72,6 +75,8 @@
#define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P')
#define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S')
#define TAG_RD11_REVERSE 0x25441313
static inline uint64_t align(uint64_t addr, size_t alignment)
{
return (addr + (alignment - 1)) & ~(alignment - 1);
@ -105,6 +110,125 @@ VKD3D_NORETURN static inline void vkd3d_unreachable_(const char *filename, unsig
#define vkd3d_unreachable() vkd3d_unreachable_(__FILE__, __LINE__)
#endif
#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);
void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback);
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
#ifndef WARN_ON
#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN)
#endif
#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)
#define VKD3D_DEBUG_ENV_NAME(name) const char *const 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]);
}
static inline const char *debugstr_hresult(HRESULT hr)
{
switch (hr)
{
#define TO_STR(u) case u: return #u;
TO_STR(S_OK)
TO_STR(S_FALSE)
TO_STR(E_NOTIMPL)
TO_STR(E_NOINTERFACE)
TO_STR(E_POINTER)
TO_STR(E_ABORT)
TO_STR(E_FAIL)
TO_STR(E_OUTOFMEMORY)
TO_STR(E_INVALIDARG)
TO_STR(DXGI_ERROR_NOT_FOUND)
TO_STR(DXGI_ERROR_MORE_DATA)
TO_STR(DXGI_ERROR_UNSUPPORTED)
#undef TO_STR
default:
return vkd3d_dbg_sprintf("%#x", (int)hr);
}
}
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);
void vkd3d_set_thread_name(const char *name);
static inline unsigned int vkd3d_popcount(unsigned int v)
{
#ifdef _MSC_VER
@ -216,6 +340,13 @@ static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)
return (x > y) - (x < y);
}
static inline int vkd3d_u64_compare(uint64_t x, uint64_t y)
{
return (x > y) - (x < y);
}
#define VKD3D_BITMAP_SIZE(x) (((x) + 0x1f) >> 5)
static inline bool bitmap_clear(uint32_t *map, unsigned int idx)
{
return map[idx >> 5] &= ~(1u << (idx & 0x1f));
@ -305,6 +436,197 @@ static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)
return vkd3d_atomic_add_fetch_u32(x, 1);
}
static inline bool vkd3d_atomic_compare_exchange_u32(uint32_t volatile *x, uint32_t expected, uint32_t val)
{
#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
return __sync_bool_compare_and_swap(x, expected, val);
#elif defined(_WIN32)
return InterlockedCompareExchange((LONG *)x, val, expected) == expected;
#else
# error "vkd3d_atomic_compare_exchange_u32() not implemented for this platform"
#endif
}
static inline bool vkd3d_atomic_compare_exchange_ptr(void * volatile *x, void *expected, void *val)
{
#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
return __sync_bool_compare_and_swap(x, expected, val);
#elif defined(_WIN32)
return InterlockedCompareExchangePointer(x, val, expected) == expected;
#else
# error "vkd3d_atomic_compare_exchange_ptr() not implemented for this platform"
#endif
}
static inline uint32_t vkd3d_atomic_exchange_u32(uint32_t volatile *x, uint32_t val)
{
#if HAVE_ATOMIC_EXCHANGE_N
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
#elif defined(_WIN32)
return InterlockedExchange((LONG *)x, val);
#else
uint32_t expected;
do
{
expected = *x;
} while (!vkd3d_atomic_compare_exchange_u32(x, expected, val));
return expected;
#endif
}
static inline void *vkd3d_atomic_exchange_ptr(void * volatile *x, void *val)
{
#if HAVE_ATOMIC_EXCHANGE_N
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
#elif defined(_WIN32)
return InterlockedExchangePointer(x, val);
#else
void *expected;
do
{
expected = *x;
} while (!vkd3d_atomic_compare_exchange_ptr(x, expected, val));
return expected;
#endif
}
struct vkd3d_mutex
{
#ifdef _WIN32
CRITICAL_SECTION lock;
#else
pthread_mutex_t lock;
#endif
};
#ifdef _WIN32
#define VKD3D_MUTEX_INITIALIZER {{NULL, -1, 0, 0, 0, 0}}
#else
#define VKD3D_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#endif
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
{
#ifdef _WIN32
InitializeCriticalSection(&lock->lock);
#else
int ret;
if ((ret = pthread_mutex_init(&lock->lock, NULL)))
ERR("Failed to initialise the mutex, ret %d.\n", ret);
#endif
}
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
{
#ifdef _WIN32
EnterCriticalSection(&lock->lock);
#else
int ret;
if ((ret = pthread_mutex_lock(&lock->lock)))
ERR("Failed to lock the mutex, ret %d.\n", ret);
#endif
}
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
{
#ifdef _WIN32
LeaveCriticalSection(&lock->lock);
#else
int ret;
if ((ret = pthread_mutex_unlock(&lock->lock)))
ERR("Failed to unlock the mutex, ret %d.\n", ret);
#endif
}
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
{
#ifdef _WIN32
DeleteCriticalSection(&lock->lock);
#else
int ret;
if ((ret = pthread_mutex_destroy(&lock->lock)))
ERR("Failed to destroy the mutex, ret %d.\n", ret);
#endif
}
struct vkd3d_cond
{
#ifdef _WIN32
CONDITION_VARIABLE cond;
#else
pthread_cond_t cond;
#endif
};
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
{
#ifdef _WIN32
InitializeConditionVariable(&cond->cond);
#else
int ret;
if ((ret = pthread_cond_init(&cond->cond, NULL)))
ERR("Failed to initialise the condition variable, ret %d.\n", ret);
#endif
}
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
{
#ifdef _WIN32
WakeConditionVariable(&cond->cond);
#else
int ret;
if ((ret = pthread_cond_signal(&cond->cond)))
ERR("Failed to signal the condition variable, ret %d.\n", ret);
#endif
}
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
{
#ifdef _WIN32
WakeAllConditionVariable(&cond->cond);
#else
int ret;
if ((ret = pthread_cond_broadcast(&cond->cond)))
ERR("Failed to broadcast the condition variable, ret %d.\n", ret);
#endif
}
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
{
#ifdef _WIN32
if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))
ERR("Failed to wait on the condition variable, error %lu.\n", GetLastError());
#else
int ret;
if ((ret = pthread_cond_wait(&cond->cond, &lock->lock)))
ERR("Failed to wait on the condition variable, ret %d.\n", ret);
#endif
}
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
{
#ifdef _WIN32
/* Nothing to do. */
#else
int ret;
if ((ret = pthread_cond_destroy(&cond->cond)))
ERR("Failed to destroy the condition variable, ret %d.\n", ret);
#endif
}
static inline void vkd3d_parse_version(const char *version, int *major, int *minor)
{
*major = atoi(version);

View File

@ -24,7 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include "vkd3d_debug.h"
#include "vkd3d_common.h"
static inline void *vkd3d_malloc(size_t size)
{
@ -65,6 +65,15 @@ static inline char *vkd3d_strdup(const char *string)
return ptr;
}
static inline void *vkd3d_memdup(const void *mem, size_t size)
{
void *ptr;
if ((ptr = vkd3d_malloc(size)))
memcpy(ptr, mem, size);
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

@ -46,21 +46,37 @@ extern "C" {
* \since 1.0
*/
/** The type of a chained structure. */
enum vkd3d_structure_type
{
/* 1.0 */
/** The structure is a vkd3d_instance_create_info structure. */
VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
/** The structure is a vkd3d_device_create_info structure. */
VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
/** The structure is a vkd3d_image_resource_create_info structure. */
VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO,
/* 1.1 */
/**
* The structure is a vkd3d_optional_instance_extensions_info structure.
* \since 1.1
*/
VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO,
/* 1.2 */
/**
* The structure is a vkd3d_optional_device_extensions_info structure.
* \since 1.2
*/
VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
/**
* The structure is a vkd3d_application_info structure.
* \since 1.2
*/
VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
/* 1.3 */
/**
* The structure is a vkd3d_host_time_domain_info structure.
* \since 1.3
*/
VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
@ -80,6 +96,7 @@ enum vkd3d_api_version
VKD3D_API_VERSION_1_9,
VKD3D_API_VERSION_1_10,
VKD3D_API_VERSION_1_11,
VKD3D_API_VERSION_1_12,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_API_VERSION),
};
@ -93,98 +110,262 @@ typedef HRESULT (*PFN_vkd3d_join_thread)(void *thread);
struct vkd3d_instance;
/**
* A chained structure containing instance creation parameters.
*/
struct vkd3d_instance_create_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/** An pointer to a function to signal events. */
PFN_vkd3d_signal_event pfn_signal_event;
/**
* An optional pointer to a function to create threads. If this is NULL vkd3d will use a
* function of its choice, depending on the platform. It must be NULL if and only if
* pfn_join_thread is NULL.
*/
PFN_vkd3d_create_thread pfn_create_thread;
/**
* An optional pointer to a function to join threads. If this is NULL vkd3d will use a
* function of its choice, depending on the platform. It must be NULL if and only if
* pfn_create_thread is NULL.
*/
PFN_vkd3d_join_thread pfn_join_thread;
/** The size of type WCHAR. It must be 2 or 4 and should normally be set to sizeof(WCHAR). */
size_t wchar_size;
/* If set to NULL, libvkd3d loads libvulkan. */
/**
* A pointer to the vkGetInstanceProcAddr Vulkan function, which will be used to load all the
* other Vulkan functions. If set to NULL, vkd3d will search and use the Vulkan loader.
*/
PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr;
/**
* A list of Vulkan instance extensions to request. They are intended as required, so instance
* creation will fail if any of them is not available.
*/
const char * const *instance_extensions;
/** The number of elements in the instance_extensions array. */
uint32_t instance_extension_count;
};
/* Extends vkd3d_instance_create_info. Available since 1.1. */
/**
* A chained structure to specify optional instance extensions.
*
* This structure extends vkd3d_instance_create_info.
*
* \since 1.1
*/
struct vkd3d_optional_instance_extensions_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/**
* A list of optional Vulkan instance extensions to request. Instance creation does not fail if
* they are not available.
*/
const char * const *extensions;
/** The number of elements in the extensions array. */
uint32_t extension_count;
};
/* Extends vkd3d_instance_create_info. Available since 1.2. */
/**
* A chained structure to specify application information.
*
* This structure extends vkd3d_instance_create_info.
*
* \since 1.2
*/
struct vkd3d_application_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_APPLICATION_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/**
* The application's name, to be passed to the Vulkan implementation. If it is NULL, a name is
* computed from the process executable filename. If that cannot be done, the empty string is
* used.
*/
const char *application_name;
/** The application's version, to be passed to the Vulkan implementation. */
uint32_t application_version;
const char *engine_name; /* "vkd3d" if NULL */
uint32_t engine_version; /* vkd3d version if engine_name is NULL */
/**
* The engine name, to be passed to the Vulkan implementation. If it is NULL, "vkd3d" is used.
*/
const char *engine_name;
/**
* The engine version, to be passed to the Vulkan implementation. If it is 0, the version is
* computed from the vkd3d library version.
*/
uint32_t engine_version;
/**
* The vkd3d API version to use, to guarantee backward compatibility of the shared library. If
* this chained structure is not used then VKD3D_API_VERSION_1_0 is used.
*/
enum vkd3d_api_version api_version;
};
/* Extends vkd3d_instance_create_info. Available since 1.3. */
/**
* A chained structure to specify the host time domain.
*
* This structure extends vkd3d_instance_create_info.
*
* \since 1.3
*/
struct vkd3d_host_time_domain_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/**
* The number of clock ticks per second, used for GetClockCalibration(). It should normally
* match the expected result of QueryPerformanceFrequency(). If this chained structure is not
* used then 10 millions is used, which means that each tick is a tenth of microsecond, or
* equivalently 100 nanoseconds.
*/
uint64_t ticks_per_second;
};
/**
* A chained structure containing device creation parameters.
*/
struct vkd3d_device_create_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/** The minimum feature level to request. Device creation will fail with E_INVALIDARG if the
* Vulkan device doesn't have the features needed to fulfill the request. */
D3D_FEATURE_LEVEL minimum_feature_level;
/**
* The vkd3d instance to use to create a device. Either this or instance_create_info must be
* set.
*/
struct vkd3d_instance *instance;
/**
* The parameters used to create an instance, which is then used to create a device. Either
* this or instance must be set.
*/
const struct vkd3d_instance_create_info *instance_create_info;
/**
* The Vulkan physical device to use. If it is NULL, the first physical device found is used,
* prioritizing discrete GPUs over integrated GPUs and integrated GPUs over all the others.
*
* This parameter can be overridden by setting environment variable VKD3D_VULKAN_DEVICE.
*/
VkPhysicalDevice vk_physical_device;
/**
* A list of Vulkan device extensions to request. They are intended as required, so device
* creation will fail if any of them is not available.
*/
const char * const *device_extensions;
/** The number of elements in the device_extensions array. */
uint32_t device_extension_count;
/**
* An object to be set as the device parent. This is not used by vkd3d except for being
* returned by vkd3d_get_device_parent.
*/
IUnknown *parent;
/**
* The adapter LUID to be set for the device. This is not used by vkd3d except for being
* returned by GetAdapterLuid.
*/
LUID adapter_luid;
};
/* Extends vkd3d_device_create_info. Available since 1.2. */
/**
* A chained structure to specify optional device extensions.
*
* This structure extends vkd3d_device_create_info.
*
* \since 1.2
*/
struct vkd3d_optional_device_extensions_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/**
* A list of optional Vulkan device extensions to request. Device creation does not fail if
* they are not available.
*/
const char * const *extensions;
/** The number of elements in the extensions array. */
uint32_t extension_count;
};
/* vkd3d_image_resource_create_info flags */
/**
* When specified as a flag of vkd3d_image_resource_create_info, it means that vkd3d will do the
* initial transition operation on the image from VK_IMAGE_LAYOUT_UNDEFINED to its appropriate
* Vulkan layout (depending on its D3D12 resource state). If this flag is not specified the caller
* is responsible for transitioning the Vulkan image to the appropriate layout.
*/
#define VKD3D_RESOURCE_INITIAL_STATE_TRANSITION 0x00000001
/**
* When specified as a flag of vkd3d_image_resource_create_info, it means that field present_state
* is honored.
*/
#define VKD3D_RESOURCE_PRESENT_STATE_TRANSITION 0x00000002
/**
* A chained structure containing the parameters to create a D3D12 resource backed by a Vulkan
* image.
*/
struct vkd3d_image_resource_create_info
{
/** Must be set to VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO. */
enum vkd3d_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/** The Vulkan image that backs the resource. */
VkImage vk_image;
/** The resource description. */
D3D12_RESOURCE_DESC desc;
/**
* A combination of zero or more flags. The valid flags are
* VKD3D_RESOURCE_INITIAL_STATE_TRANSITION and VKD3D_RESOURCE_PRESENT_STATE_TRANSITION.
*/
unsigned int flags;
/**
* This field specifies how to handle resource state D3D12_RESOURCE_STATE_PRESENT for
* the resource. Notice that on D3D12 there is no difference between
* D3D12_RESOURCE_STATE_COMMON and D3D12_RESOURCE_STATE_PRESENT (they have the same value),
* while on Vulkan two different layouts are used (VK_IMAGE_LAYOUT_GENERAL and
* VK_IMAGE_LAYOUT_PRESENT_SRC_KHR).
*
* * When flag VKD3D_RESOURCE_PRESENT_STATE_TRANSITION is not specified, field
* present_state is ignored and resource state D3D12_RESOURCE_STATE_COMMON/_PRESENT is
* mapped to VK_IMAGE_LAYOUT_GENERAL; this is useful for non-swapchain resources.
* * Otherwise, when present_state is D3D12_RESOURCE_STATE_PRESENT/_COMMON, resource state
* D3D12_RESOURCE_STATE_COMMON/_PRESENT is mapped to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
* this is useful for swapchain resources that are directly backed by a Vulkan swapchain
* image.
* * Otherwise, resource state D3D12_RESOURCE_STATE_COMMON/_PRESENT is treated as resource
* state present_state; this is useful for swapchain resources that backed by a Vulkan
* non-swapchain image, which the client will likely consume with a copy or drawing
* operation at presentation time.
*/
D3D12_RESOURCE_STATES present_state;
};

View File

@ -21,6 +21,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <vkd3d_types.h>
#ifdef __cplusplus
@ -53,6 +54,7 @@ enum vkd3d_shader_api_version
VKD3D_SHADER_API_VERSION_1_9,
VKD3D_SHADER_API_VERSION_1_10,
VKD3D_SHADER_API_VERSION_1_11,
VKD3D_SHADER_API_VERSION_1_12,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_API_VERSION),
};
@ -148,6 +150,12 @@ enum vkd3d_shader_compile_option_formatting_flags
VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS = 0x00000004,
VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER = 0x00000008,
VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS = 0x00000010,
/**
* Emit the signatures when disassembling a shader.
*
* \since 1.12
*/
VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES = 0x00000020,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FORMATTING_FLAGS),
};
@ -208,10 +216,33 @@ enum vkd3d_shader_compile_option_feature_flags
* This corresponds to the "shaderFloat64" feature in the Vulkan API, and
* the "GL_ARB_gpu_shader_fp64" extension in the OpenGL API. */
VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64 = 0x00000002,
/** The SPIR-V target environment supports wave operations.
* This flag is valid only in VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1
* or greater, and corresponds to the following minimum requirements in
* VkPhysicalDeviceSubgroupProperties:
* - subgroupSize >= 4.
* - supportedOperations has BASIC, VOTE, ARITHMETIC, BALLOT, SHUFFLE and
* QUAD bits set.
* - supportedStages include COMPUTE and FRAGMENT. \since 1.12 */
VKD3D_SHADER_COMPILE_OPTION_FEATURE_WAVE_OPS = 0x00000004,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS),
};
/**
* Flags for vkd3d_shader_parse_dxbc().
*
* \since 1.12
*/
enum vkd3d_shader_parse_dxbc_flags
{
/** Ignore the checksum and continue parsing even if it is
* incorrect. */
VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM = 0x00000001,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARSE_DXBC_FLAGS),
};
enum vkd3d_shader_compile_option_name
{
/**
@ -279,6 +310,36 @@ enum vkd3d_shader_compile_option_name
* \since 1.11
*/
VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a,
/**
* If \a value is non-zero compilation will produce a child effect using
* shared object descriptions, as instructed by the "shared" modifier.
* Child effects are supported with fx_4_0, and fx_4_1 profiles. This option
* and "shared" modifiers are ignored for the fx_5_0 profile and non-fx profiles.
* The fx_2_0 profile does not have a separate concept of child effects, variables
* marked with "shared" modifier will be marked as such in a binary.
*
* \since 1.12
*/
VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT = 0x0000000b,
/**
* If \a value is nonzero, emit a compile warning warn when vectors or
* matrices are truncated in an implicit conversion.
* If warnings are disabled, this option has no effect.
* This option has no effects for targets other than HLSL.
*
* The default value is nonzero, i.e. enable implicit truncation warnings.
*
* \since 1.12
*/
VKD3D_SHADER_COMPILE_OPTION_WARN_IMPLICIT_TRUNCATION = 0x0000000c,
/**
* If \a value is nonzero, empty constant buffers descriptions are
* written out in the output effect binary. This option applies only
* to fx_4_0 and fx_4_1 profiles and is otherwise ignored.
*
* \since 1.12
*/
VKD3D_SHADER_COMPILE_OPTION_INCLUDE_EMPTY_BUFFERS_IN_EFFECTS = 0x0000000d,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
};
@ -872,6 +933,8 @@ enum vkd3d_shader_spirv_environment
VKD3D_SHADER_SPIRV_ENVIRONMENT_NONE,
VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5,
VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, /* default target */
/** \since 1.12 */
VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_ENVIRONMENT),
};
@ -886,6 +949,8 @@ enum vkd3d_shader_spirv_extension
VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT,
/** \since 1.11 */
VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER,
/** \since 1.12 */
VKD3D_SHADER_SPIRV_EXTENSION_EXT_FRAGMENT_SHADER_INTERLOCK,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_EXTENSION),
};
@ -1995,8 +2060,12 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported
* - VKD3D_SHADER_SOURCE_D3D_BYTECODE to VKD3D_SHADER_TARGET_SPIRV_TEXT
* (if vkd3d was compiled with SPIRV-Tools)
* - VKD3D_SHADER_SOURCE_D3D_BYTECODE to VKD3D_SHADER_TARGET_D3D_ASM
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_DXBC_TPF
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_SPIRV_BINARY
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_SPIRV_TEXT
* (if vkd3d was compiled with SPIRV-Tools)
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_D3D_ASM
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_D3D_BYTECODE
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_DXBC_TPF
* - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_FX
*
* Supported transformations can also be detected at runtime with the functions
@ -2377,9 +2446,8 @@ VKD3D_SHADER_API void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc
*
* \param dxbc A vkd3d_shader_code structure containing the DXBC blob to parse.
*
* \param flags A set of flags modifying the behaviour of the function. No
* flags are defined for this version of vkd3d-shader, and this parameter
* should be set to 0.
* \param flags A combination of zero or more elements of enum
* vkd3d_shader_parse_dxbc_flags.
*
* \param desc A vkd3d_shader_dxbc_desc structure describing the contents of
* the DXBC blob. Its vkd3d_shader_dxbc_section_desc structures will contain

View File

@ -41,6 +41,8 @@ enum vkd3d_result
{
/** Success. */
VKD3D_OK = 0,
/** Success as a result of there being nothing to do. \since 1.12 */
VKD3D_FALSE = 1,
/** An unspecified failure occurred. */
VKD3D_ERROR = -1,
/** There are not enough resources available to complete the operation. */
@ -51,6 +53,12 @@ enum vkd3d_result
VKD3D_ERROR_INVALID_SHADER = -4,
/** The operation is not implemented in this version of vkd3d. */
VKD3D_ERROR_NOT_IMPLEMENTED = -5,
/** The object or entry already exists. \since 1.12 */
VKD3D_ERROR_KEY_ALREADY_EXISTS = -6,
/** The requested object was not found. \since 1.12 */
VKD3D_ERROR_NOT_FOUND = -7,
/** The output buffer is larger than the requested object \since 1.12. */
VKD3D_ERROR_MORE_DATA = -8,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_RESULT),
};

View File

@ -16,12 +16,15 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __MINGW32__
#define WIDL_C_INLINE_WRAPPERS
#endif
#define COBJMACROS
#define CONST_VTABLE
#include "vkd3d.h"
#include "vkd3d_blob.h"
#include "vkd3d_debug.h"
#include "vkd3d_memory.h"
#include "d3d12shader.h"
struct vkd3d_blob
{

View File

@ -20,7 +20,7 @@
# define _WIN32_WINNT 0x0600 /* For InitOnceExecuteOnce(). */
#endif
#include "vkd3d_debug.h"
#include "vkd3d_common.h"
#include <assert.h>
#include <ctype.h>

View File

@ -17,7 +17,6 @@
*/
#include "vkd3d_common.h"
#include "vkd3d_debug.h"
HRESULT hresult_from_vkd3d_result(int vkd3d_result)
{
@ -36,6 +35,12 @@ HRESULT hresult_from_vkd3d_result(int vkd3d_result)
return E_INVALIDARG;
case VKD3D_ERROR_NOT_IMPLEMENTED:
return E_NOTIMPL;
case VKD3D_ERROR_KEY_ALREADY_EXISTS:
return DXGI_ERROR_ALREADY_EXISTS;
case VKD3D_ERROR_NOT_FOUND:
return DXGI_ERROR_NOT_FOUND;
case VKD3D_ERROR_MORE_DATA:
return DXGI_ERROR_MORE_DATA;
default:
FIXME("Unhandled vkd3d result %d.\n", vkd3d_result);
return E_FAIL;

File diff suppressed because it is too large Load Diff

View File

@ -215,8 +215,12 @@ struct vkd3d_shader_sm1_parser
struct vkd3d_shader_parser p;
struct
{
#define MAX_CONSTANT_COUNT 8192
uint32_t constant_def_mask[3][MAX_CONSTANT_COUNT / 32];
uint32_t def_mask[VKD3D_BITMAP_SIZE(MAX_CONSTANT_COUNT)];
uint32_t count;
} constants[3];
};
/* This table is not order or position dependent. */
@ -392,11 +396,6 @@ static const enum vkd3d_shader_resource_type resource_type_table[] =
/* 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)++;
@ -414,7 +413,7 @@ static bool has_relative_address(uint32_t param)
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_shader_version *version = &sm1->p.program.shader_version;
const struct vkd3d_shader_version *version = &sm1->p.program->shader_version;
const struct vkd3d_sm1_opcode_info *info;
unsigned int i = 0;
@ -537,13 +536,14 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval,
unsigned int register_index, bool is_dcl, unsigned int mask)
{
struct vsir_program *program = sm1->p.program;
struct shader_signature *signature;
struct signature_element *element;
if (output)
signature = &sm1->p.shader_desc.output_signature;
signature = &program->output_signature;
else
signature = &sm1->p.shader_desc.input_signature;
signature = &program->input_signature;
if ((element = find_signature_element(signature, name, index)))
{
@ -559,7 +559,8 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element = &signature->elements[signature->element_count++];
memset(element, 0, sizeof(*element));
element->semantic_name = name;
if (!(element->semantic_name = vkd3d_strdup(name)))
return false;
element->semantic_index = index;
element->sysval_semantic = sysval;
element->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
@ -568,7 +569,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element->register_count = 1;
element->mask = mask;
element->used_mask = is_dcl ? 0 : mask;
if (sm1->p.program.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
element->interpolation_mode = VKD3DSIM_LINEAR;
return true;
@ -577,13 +578,14 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output,
unsigned int register_index, unsigned int mask)
{
struct vsir_program *program = sm1->p.program;
struct shader_signature *signature;
struct signature_element *element;
if (output)
signature = &sm1->p.shader_desc.output_signature;
signature = &program->output_signature;
else
signature = &sm1->p.shader_desc.input_signature;
signature = &program->input_signature;
if (!(element = find_signature_element_by_register_index(signature, register_index)))
{
@ -598,7 +600,7 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output,
static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask)
{
const struct vkd3d_shader_version *version = &sm1->p.program.shader_version;
const struct vkd3d_shader_version *version = &sm1->p.program->shader_version;
unsigned int register_index = reg->idx[0].offset;
switch (reg->type)
@ -701,7 +703,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_semantic *semantic)
{
const struct vkd3d_shader_version *version = &sm1->p.program.shader_version;
const struct vkd3d_shader_version *version = &sm1->p.program->shader_version;
const struct vkd3d_shader_register *reg = &semantic->resource.reg.reg;
enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE;
unsigned int mask = semantic->resource.reg.write_mask;
@ -750,22 +752,20 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1,
enum vkd3d_shader_d3dbc_constant_register set, uint32_t index, bool from_def)
{
struct vkd3d_shader_desc *desc = &sm1->p.shader_desc;
desc->flat_constant_count[set].used = max(desc->flat_constant_count[set].used, index + 1);
sm1->constants[set].count = max(sm1->constants[set].count, index + 1);
if (from_def)
{
/* d3d shaders have a maximum of 8192 constants; we should not overrun
* this array. */
assert((index / 32) <= ARRAY_SIZE(sm1->constant_def_mask[set]));
bitmap_set(sm1->constant_def_mask[set], index);
assert((index / 32) <= ARRAY_SIZE(sm1->constants[set].def_mask));
bitmap_set(sm1->constants[set].def_mask, index);
}
}
static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_register *reg, unsigned int mask, bool from_def)
{
struct vsir_program *program = &sm1->p.program;
struct vsir_program *program = sm1->p.program;
uint32_t register_index = reg->idx[0].offset;
switch (reg->type)
@ -826,7 +826,7 @@ static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1,
* 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.program.shader_version.major < 2)
if (sm1->p.program->shader_version.major < 2)
{
*addr_token = (1u << 31)
| ((VKD3DSPR_ADDR << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2)
@ -855,7 +855,7 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co
/* 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.program.shader_version.major >= 2)
if (sm1->p.program->shader_version.major >= 2)
{
length = (opcode_token & VKD3D_SM1_INSTRUCTION_LENGTH_MASK) >> VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT;
*ptr += length;
@ -881,15 +881,6 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co
*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);
vsir_program_cleanup(&parser->program);
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)
{
@ -899,7 +890,7 @@ static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
{
if (!(src_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1)))
if (!(src_rel_addr = vsir_program_get_src_params(sm1->p.program, 1)))
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Out of memory.");
@ -920,7 +911,7 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const
shader_sm1_read_param(sm1, ptr, &token, &addr_token);
if (has_relative_address(token))
{
if (!(dst_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1)))
if (!(dst_rel_addr = vsir_program_get_src_params(sm1->p.program, 1)))
{
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY,
"Out of memory.");
@ -1089,7 +1080,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
{
struct vkd3d_shader_src_param *src_params, *predicate;
const struct vkd3d_sm1_opcode_info *opcode_info;
struct vsir_program *program = &sm1->p.program;
struct vsir_program *program = sm1->p.program;
struct vkd3d_shader_dst_param *dst_param;
const uint32_t **ptr = &sm1->ptr;
uint32_t opcode_token;
@ -1226,18 +1217,12 @@ static bool shader_sm1_is_end(struct vkd3d_shader_sm1_parser *sm1)
return false;
}
const struct vkd3d_shader_parser_ops shader_sm1_parser_ops =
{
.parser_destroy = shader_sm1_destroy,
};
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, struct vsir_program *program,
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;
@ -1287,12 +1272,10 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
sm1->end = &code[token_count];
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops,
code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
if (!vsir_program_init(program, &version, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
return VKD3D_ERROR_OUT_OF_MEMORY;
shader_desc = &sm1->p.shader_desc;
shader_desc->byte_code = code;
shader_desc->byte_code_size = code_size;
vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name);
sm1->ptr = sm1->start;
return VKD3D_OK;
@ -1306,77 +1289,68 @@ static uint32_t get_external_constant_count(struct vkd3d_shader_sm1_parser *sm1,
/* Find the highest constant index which is not written by a DEF
* instruction. We can't (easily) use an FFZ function for this since it
* needs to be limited by the highest used register index. */
for (j = sm1->p.shader_desc.flat_constant_count[set].used; j > 0; --j)
for (j = sm1->constants[set].count; j > 0; --j)
{
if (!bitmap_is_set(sm1->constant_def_mask[set], j - 1))
if (!bitmap_is_set(sm1->constants[set].def_mask, j - 1))
return j;
}
return 0;
}
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)
int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program)
{
struct vkd3d_shader_instruction_array *instructions;
struct vkd3d_shader_sm1_parser sm1 = {0};
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_sm1_parser *sm1;
unsigned int i;
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)
if ((ret = shader_sm1_init(&sm1, program, compile_info, message_context)) < 0)
{
WARN("Failed to initialise shader parser, ret %d.\n", ret);
vkd3d_free(sm1);
return ret;
}
instructions = &sm1->p.program.instructions;
while (!shader_sm1_is_end(sm1))
instructions = &program->instructions;
while (!shader_sm1_is_end(&sm1))
{
if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
{
ERR("Failed to allocate instructions.\n");
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory.");
shader_sm1_destroy(&sm1->p);
vkd3d_shader_parser_error(&sm1.p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory.");
vsir_program_cleanup(program);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
ins = &instructions->elements[instructions->count];
shader_sm1_read_instruction(sm1, ins);
shader_sm1_read_instruction(&sm1, ins);
if (ins->handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
shader_sm1_destroy(&sm1->p);
vsir_program_cleanup(program);
return VKD3D_ERROR_INVALID_SHADER;
}
++instructions->count;
}
for (i = 0; i < ARRAY_SIZE(sm1->p.shader_desc.flat_constant_count); ++i)
sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i);
for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i)
program->flat_constant_count[i] = get_external_constant_count(&sm1, i);
if (!sm1->p.failed)
ret = vsir_validate(&sm1->p);
if (!sm1.p.failed)
ret = vkd3d_shader_parser_validate(&sm1.p, config_flags);
if (sm1->p.failed && ret >= 0)
if (sm1.p.failed && ret >= 0)
ret = VKD3D_ERROR_INVALID_SHADER;
if (ret < 0)
{
WARN("Failed to parse shader.\n");
shader_sm1_destroy(&sm1->p);
vsir_program_cleanup(program);
return ret;
}
*parser = &sm1->p;
return ret;
}
@ -1499,47 +1473,74 @@ static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, uns
return D3DPS_VERSION(major, minor);
}
static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type)
D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type)
{
switch (type->class)
{
case HLSL_CLASS_ARRAY:
return sm1_class(type->e.array.type);
return hlsl_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->class);
vkd3d_unreachable();
case HLSL_CLASS_PIXEL_SHADER:
case HLSL_CLASS_SAMPLER:
case HLSL_CLASS_STRING:
case HLSL_CLASS_TEXTURE:
case HLSL_CLASS_VERTEX_SHADER:
return D3DXPC_OBJECT;
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
case HLSL_CLASS_EFFECT_GROUP:
case HLSL_CLASS_PASS:
case HLSL_CLASS_RENDER_TARGET_VIEW:
case HLSL_CLASS_TECHNIQUE:
case HLSL_CLASS_UAV:
case HLSL_CLASS_VOID:
break;
}
vkd3d_unreachable();
}
static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type)
D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type)
{
switch (type->base_type)
switch (type->class)
{
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:
case HLSL_CLASS_SCALAR:
case HLSL_CLASS_VECTOR:
case HLSL_CLASS_MATRIX:
switch (type->e.numeric.type)
{
case HLSL_TYPE_BOOL:
return D3DXPT_BOOL;
/* Actually double behaves differently depending on DLL version:
* For <= 36, it maps to D3DXPT_FLOAT.
* For 37-40, it maps to zero (D3DXPT_VOID).
* For >= 41, it maps to 39, which is D3D_SVT_DOUBLE (note D3D_SVT_*
* values are mostly compatible with D3DXPT_*).
* However, the latter two cases look like bugs, and a reasonable
* application certainly wouldn't know what to do with them.
* For fx_2_0 it's always D3DXPT_FLOAT regardless of DLL version. */
case HLSL_TYPE_DOUBLE:
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
return D3DXPT_FLOAT;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
return D3DXPT_INT;
default:
vkd3d_unreachable();
}
case HLSL_CLASS_SAMPLER:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
@ -1557,9 +1558,8 @@ static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type)
vkd3d_unreachable();
}
break;
case HLSL_TYPE_STRING:
return D3DXPT_STRING;
case HLSL_TYPE_TEXTURE:
case HLSL_CLASS_TEXTURE:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
@ -1577,13 +1577,33 @@ static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type)
vkd3d_unreachable();
}
break;
case HLSL_TYPE_VERTEXSHADER:
return D3DXPT_VERTEXSHADER;
case HLSL_TYPE_VOID:
case HLSL_CLASS_ARRAY:
return hlsl_sm1_base_type(type->e.array.type);
case HLSL_CLASS_STRUCT:
return D3DXPT_VOID;
default:
vkd3d_unreachable();
case HLSL_CLASS_STRING:
return D3DXPT_STRING;
case HLSL_CLASS_PIXEL_SHADER:
return D3DXPT_PIXELSHADER;
case HLSL_CLASS_VERTEX_SHADER:
return D3DXPT_VERTEXSHADER;
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
case HLSL_CLASS_EFFECT_GROUP:
case HLSL_CLASS_PASS:
case HLSL_CLASS_RENDER_TARGET_VIEW:
case HLSL_CLASS_TECHNIQUE:
case HLSL_CLASS_UAV:
case HLSL_CLASS_VOID:
break;
}
vkd3d_unreachable();
}
static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_type *type, unsigned int ctab_start)
@ -1620,7 +1640,7 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_typ
}
}
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm1_class(type), sm1_base_type(array_type)));
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_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);
@ -1670,7 +1690,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
for (r = 0; r <= HLSL_REGSET_LAST; ++r)
{
if (var->semantic.name || !var->regs[r].allocated)
if (var->semantic.name || !var->regs[r].allocated || !var->last_read)
continue;
++uniform_count;
@ -1708,14 +1728,14 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
for (r = 0; r <= HLSL_REGSET_LAST; ++r)
{
if (var->semantic.name || !var->regs[r].allocated)
if (var->semantic.name || !var->regs[r].allocated || !var->last_read)
continue;
put_u32(buffer, 0); /* name */
if (r == HLSL_REGSET_NUMERIC)
{
put_u32(buffer, vkd3d_make_u32(D3DXRS_FLOAT4, var->regs[r].id));
put_u32(buffer, var->data_type->reg_size[r] / 4);
put_u32(buffer, var->bind_count[r]);
}
else
{
@ -1737,7 +1757,7 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe
{
size_t var_offset, name_offset;
if (var->semantic.name || !var->regs[r].allocated)
if (var->semantic.name || !var->regs[r].allocated || !var->last_read)
continue;
var_offset = vars_start + (uniform_count * 5 * sizeof(uint32_t));
@ -1767,6 +1787,7 @@ static uint32_t sm1_encode_register_type(D3DSHADER_PARAM_REGISTER_TYPE type)
struct sm1_instruction
{
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode;
unsigned int flags;
struct sm1_dst_register
{
@ -1806,6 +1827,8 @@ static void write_sm1_instruction(struct hlsl_ctx *ctx, struct vkd3d_bytecode_bu
uint32_t token = instr->opcode;
unsigned int i;
token |= VKD3D_SM1_INSTRUCTION_FLAGS_MASK & (instr->flags << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT);
if (ctx->profile->major_version > 1)
token |= (instr->has_dst + instr->src_count) << D3DSI_INSTLENGTH_SHIFT;
put_u32(buffer, token);
@ -1969,24 +1992,21 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
/* Narrowing casts were already lowered. */
assert(src_type->dimx == dst_type->dimx);
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
/* Integers are internally represented as floats, so no change is necessary.*/
case HLSL_TYPE_BOOL:
/* Integrals are internally represented as floats, so no change is necessary.*/
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0);
break;
case HLSL_TYPE_BOOL:
hlsl_fixme(ctx, &instr->loc, "SM1 cast from bool to float.");
break;
case HLSL_TYPE_DOUBLE:
hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float.");
break;
@ -1998,11 +2018,14 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
switch(src_type->base_type)
switch(src_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
/* A compilation pass applies a FLOOR operation to casts to int, so no change is necessary. */
/* A compilation pass turns these into FLOOR+REINTERPRET, so we should not
* reach this case unless we are missing something. */
hlsl_fixme(ctx, &instr->loc, "Unlowered SM1 cast from float to integer.");
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0);
@ -2028,7 +2051,7 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
case HLSL_TYPE_BOOL:
/* Casts to bool should have already been lowered. */
default:
hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.\n",
hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.",
debug_hlsl_type(ctx, src_type), debug_hlsl_type(ctx, dst_type));
break;
}
@ -2067,6 +2090,9 @@ static void write_sm1_semantic_dcl(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
D3DDECLUSAGE usage;
bool ret;
if ((!output && !var->last_read) || (output && !var->first_write))
return;
if (hlsl_sm1_register_from_semantic(ctx, &var->semantic, output, &reg.type, &reg.reg))
{
usage = 0;
@ -2242,13 +2268,19 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
assert(instr->reg.allocated);
if (expr->op == HLSL_OP1_REINTERPRET)
{
write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0);
return;
}
if (expr->op == HLSL_OP1_CAST)
{
write_sm1_cast(ctx, buffer, instr);
return;
}
if (instr->data_type->base_type != HLSL_TYPE_FLOAT)
if (instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT)
{
/* These need to be lowered. */
hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression.");
@ -2329,7 +2361,23 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
}
break;
case HLSL_OP2_LOGIC_AND:
write_sm1_binary_op(ctx, buffer, D3DSIO_MIN, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP2_LOGIC_OR:
write_sm1_binary_op(ctx, buffer, D3DSIO_MAX, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP2_SLT:
if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
hlsl_fixme(ctx, &instr->loc, "Lower SLT instructions for pixel shaders.");
write_sm1_binary_op(ctx, buffer, D3DSIO_SLT, &instr->reg, &arg1->reg, &arg2->reg);
break;
case HLSL_OP3_CMP:
if (ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX)
hlsl_fixme(ctx, &instr->loc, "Lower CMP instructions for vertex shaders.");
write_sm1_ternary_op(ctx, buffer, D3DSIO_CMP, &instr->reg, &arg1->reg, &arg2->reg, &arg3->reg);
break;
@ -2343,6 +2391,49 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
}
}
static void write_sm1_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_block *block);
static void write_sm1_if(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_if *iff = hlsl_ir_if(instr);
const struct hlsl_ir_node *condition;
struct sm1_instruction sm1_ifc, sm1_else, sm1_endif;
condition = iff->condition.node;
assert(condition->data_type->dimx == 1 && condition->data_type->dimy == 1);
sm1_ifc = (struct sm1_instruction)
{
.opcode = D3DSIO_IFC,
.flags = VKD3D_SHADER_REL_OP_NE, /* Make it a "if_ne" instruction. */
.srcs[0].type = D3DSPR_TEMP,
.srcs[0].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask),
.srcs[0].reg = condition->reg.id,
.srcs[0].mod = 0,
.srcs[1].type = D3DSPR_TEMP,
.srcs[1].swizzle = hlsl_swizzle_from_writemask(condition->reg.writemask),
.srcs[1].reg = condition->reg.id,
.srcs[1].mod = D3DSPSM_NEG,
.src_count = 2,
};
write_sm1_instruction(ctx, buffer, &sm1_ifc);
write_sm1_block(ctx, buffer, &iff->then_block);
if (!list_empty(&iff->else_block.instrs))
{
sm1_else = (struct sm1_instruction){.opcode = D3DSIO_ELSE};
write_sm1_instruction(ctx, buffer, &sm1_else);
write_sm1_block(ctx, buffer, &iff->else_block);
}
sm1_endif = (struct sm1_instruction){.opcode = D3DSIO_ENDIF};
write_sm1_instruction(ctx, buffer, &sm1_endif);
}
static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr)
{
const struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
@ -2368,7 +2459,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
}
default:
hlsl_fixme(ctx, &jump->node.loc, "Jump type %s.\n", hlsl_jump_type_to_string(jump->type));
hlsl_fixme(ctx, &jump->node.loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
}
}
@ -2456,7 +2547,7 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_
break;
default:
hlsl_fixme(ctx, &instr->loc, "Resource load type %u\n", load->load_type);
hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type);
return;
}
@ -2488,7 +2579,7 @@ static void write_sm1_store(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *
if (store->lhs.var->data_type->class == HLSL_CLASS_MATRIX)
{
FIXME("Matrix writemasks need to be lowered.\n");
hlsl_fixme(ctx, &instr->loc, "Lower matrix writemasks.");
return;
}
@ -2543,28 +2634,20 @@ static void write_sm1_swizzle(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
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)
static void write_sm1_block(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_block *block)
{
const struct hlsl_ir_node *instr;
LIST_FOR_EACH_ENTRY(instr, &entry_func->body.instrs, struct hlsl_ir_node, entry)
LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
{
if (instr->data_type)
{
if (instr->data_type->class == HLSL_CLASS_MATRIX)
if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
{
/* These need to be lowered. */
hlsl_fixme(ctx, &instr->loc, "SM1 matrix expression.");
continue;
}
else if (instr->data_type->class == HLSL_CLASS_OBJECT)
{
hlsl_fixme(ctx, &instr->loc, "Object copy.");
hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class);
break;
}
assert(instr->data_type->class == HLSL_CLASS_SCALAR || instr->data_type->class == HLSL_CLASS_VECTOR);
}
switch (instr->type)
@ -2580,6 +2663,13 @@ static void write_sm1_instructions(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
write_sm1_expr(ctx, buffer, instr);
break;
case HLSL_IR_IF:
if (hlsl_version_ge(ctx, 2, 1))
write_sm1_if(ctx, buffer, instr);
else
hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches.");
break;
case HLSL_IR_JUMP:
write_sm1_jump(ctx, buffer, instr);
break;
@ -2617,7 +2707,7 @@ int hlsl_sm1_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun
write_sm1_constant_defs(ctx, &buffer);
write_sm1_semantic_dcls(ctx, &buffer);
write_sm1_sampler_dcls(ctx, &buffer);
write_sm1_instructions(ctx, &buffer, entry_func);
write_sm1_block(ctx, &buffer, &entry_func->body);
put_u32(&buffer, D3DSIO_END);

View File

@ -150,7 +150,7 @@ static const char *shader_get_string(const char *data, size_t data_size, size_t
}
static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context,
const char *source_name, struct vkd3d_shader_dxbc_desc *desc)
const char *source_name, uint32_t flags, struct vkd3d_shader_dxbc_desc *desc)
{
const struct vkd3d_shader_location location = {.source_name = source_name};
struct vkd3d_shader_dxbc_section_desc *sections, *section;
@ -186,17 +186,20 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_
checksum[1] = read_u32(&ptr);
checksum[2] = read_u32(&ptr);
checksum[3] = read_u32(&ptr);
vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum);
if (memcmp(checksum, calculated_checksum, sizeof(checksum)))
if (!(flags & VKD3D_SHADER_PARSE_DXBC_IGNORE_CHECKSUM))
{
WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match "
"calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
checksum[0], checksum[1], checksum[2], checksum[3],
calculated_checksum[0], calculated_checksum[1],
calculated_checksum[2], calculated_checksum[3]);
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM,
"Invalid DXBC checksum.");
return VKD3D_ERROR_INVALID_ARGUMENT;
vkd3d_compute_dxbc_checksum(data, data_size, calculated_checksum);
if (memcmp(checksum, calculated_checksum, sizeof(checksum)))
{
WARN("Checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x} does not match "
"calculated checksum {0x%08x, 0x%08x, 0x%08x, 0x%08x}.\n",
checksum[0], checksum[1], checksum[2], checksum[3],
calculated_checksum[0], calculated_checksum[1],
calculated_checksum[2], calculated_checksum[3]);
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHECKSUM,
"Invalid DXBC checksum.");
return VKD3D_ERROR_INVALID_ARGUMENT;
}
}
version = read_u32(&ptr);
@ -287,7 +290,7 @@ static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
unsigned int i;
int ret;
if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0)
if ((ret = parse_dxbc(dxbc, message_context, source_name, 0, &desc)) < 0)
return ret;
for (i = 0; i < desc.section_count; ++i)
@ -313,7 +316,7 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = parse_dxbc(dxbc, &message_context, NULL, desc);
ret = parse_dxbc(dxbc, &message_context, NULL, flags, desc);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0)
@ -357,7 +360,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
uint32_t count, header_size;
struct signature_element *e;
const char *ptr = data;
unsigned int i;
unsigned int i, j;
if (!require_space(0, 2, sizeof(uint32_t), section->data.size))
{
@ -400,6 +403,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
for (i = 0; i < count; ++i)
{
size_t name_offset;
const char *name;
uint32_t mask;
e[i].sort_index = i;
@ -410,9 +414,14 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
e[i].stream_index = 0;
name_offset = read_u32(&ptr);
if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset)))
if (!(name = shader_get_string(data, section->data.size, name_offset))
|| !(e[i].semantic_name = vkd3d_strdup(name)))
{
WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size);
for (j = 0; j < i; ++j)
{
vkd3d_free((void *)e[j].semantic_name);
}
vkd3d_free(e);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@ -485,7 +494,7 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_message_context *message_context, void *context)
{
struct vkd3d_shader_desc *desc = context;
struct dxbc_shader_desc *desc = context;
int ret;
switch (section->tag)
@ -550,7 +559,7 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section,
return VKD3D_OK;
}
void free_shader_desc(struct vkd3d_shader_desc *desc)
void free_dxbc_shader_desc(struct dxbc_shader_desc *desc)
{
shader_signature_cleanup(&desc->input_signature);
shader_signature_cleanup(&desc->output_signature);
@ -558,7 +567,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc)
}
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc)
struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc)
{
int ret;
@ -569,7 +578,7 @@ int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
if (ret < 0)
{
WARN("Failed to parse shader, vkd3d result %d.\n", ret);
free_shader_desc(desc);
free_dxbc_shader_desc(desc);
}
return ret;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,29 +20,14 @@
struct vkd3d_glsl_generator
{
struct vkd3d_shader_version version;
struct vsir_program *program;
struct vkd3d_string_buffer buffer;
struct vkd3d_shader_location location;
struct vkd3d_shader_message_context *message_context;
unsigned int indent;
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, ...)
@ -55,10 +40,23 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error(
generator->failed = true;
}
static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent)
{
vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, "");
}
static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins)
{
shader_glsl_print_indent(&gen->buffer, gen->indent);
vkd3d_string_buffer_printf(&gen->buffer, "/* <unhandled instruction %#x> */\n", ins->handler_idx);
vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL,
"Internal compiler error: Unhandled instruction %#x.", ins->handler_idx);
}
static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
const struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_shader_version *version = &generator->version;
const struct vkd3d_shader_version *version = &generator->program->shader_version;
/*
* TODO: Implement in_subroutine
@ -66,6 +64,7 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
*/
if (version->major >= 4)
{
shader_glsl_print_indent(&generator->buffer, generator->indent);
vkd3d_string_buffer_printf(&generator->buffer, "return;\n");
}
}
@ -73,48 +72,57 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator,
static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator,
const struct vkd3d_shader_instruction *instruction)
{
generator->location = instruction->location;
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_INPUT:
case VKD3DSIH_DCL_OUTPUT:
case VKD3DSIH_DCL_OUTPUT_SIV:
case VKD3DSIH_NOP:
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);
shader_glsl_unhandled(generator, instruction);
break;
}
}
int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
struct vsir_program *program, struct vkd3d_shader_code *out)
static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struct vkd3d_shader_code *out)
{
const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions;
struct vkd3d_string_buffer *buffer = &gen->buffer;
unsigned int i;
void *code;
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n");
vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
ERR("Generating a GLSL shader. This is unsupported; you get to keep all the pieces if it breaks.\n");
generator->location.column = 0;
for (i = 0; i < program->instructions.count; ++i)
vkd3d_string_buffer_printf(buffer, "#version 440\n\n");
vkd3d_string_buffer_printf(buffer, "/* Generated by %s. */\n\n", vkd3d_shader_get_version(NULL, NULL));
vkd3d_string_buffer_printf(buffer, "void main()\n{\n");
++gen->indent;
for (i = 0; i < instructions->count; ++i)
{
generator->location.line = i + 1;
vkd3d_glsl_handle_instruction(generator, &program->instructions.elements[i]);
vkd3d_glsl_handle_instruction(gen, &instructions->elements[i]);
}
if (generator->failed)
vkd3d_string_buffer_printf(buffer, "}\n");
if (TRACE_ON())
vkd3d_string_buffer_trace(buffer);
if (gen->failed)
return VKD3D_ERROR_INVALID_SHADER;
vkd3d_string_buffer_printf(&generator->buffer, "}\n");
if ((code = vkd3d_malloc(generator->buffer.buffer_size)))
if ((code = vkd3d_malloc(buffer->buffer_size)))
{
memcpy(code, generator->buffer.buffer, generator->buffer.content_size);
out->size = generator->buffer.content_size;
memcpy(code, buffer->buffer, buffer->content_size);
out->size = buffer->content_size;
out->code = code;
}
else return VKD3D_ERROR_OUT_OF_MEMORY;
@ -122,8 +130,33 @@ int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
return VKD3D_OK;
}
void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator)
static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen)
{
vkd3d_string_buffer_cleanup(&generator->buffer);
vkd3d_free(generator);
vkd3d_string_buffer_cleanup(&gen->buffer);
}
static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen,
struct vsir_program *program, struct vkd3d_shader_message_context *message_context)
{
memset(gen, 0, sizeof(*gen));
gen->program = program;
vkd3d_string_buffer_init(&gen->buffer);
gen->message_context = message_context;
}
int glsl_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_glsl_generator generator;
int ret;
if ((ret = vsir_program_normalise(program, config_flags, compile_info, message_context)) < 0)
return ret;
vkd3d_glsl_generator_init(&generator, program, message_context);
ret = vkd3d_glsl_generator_generate(&generator, out);
vkd3d_glsl_generator_cleanup(&generator);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,18 @@ enum hlsl_type_class
HLSL_CLASS_LAST_NUMERIC = HLSL_CLASS_MATRIX,
HLSL_CLASS_STRUCT,
HLSL_CLASS_ARRAY,
HLSL_CLASS_OBJECT,
HLSL_CLASS_DEPTH_STENCIL_VIEW,
HLSL_CLASS_EFFECT_GROUP,
HLSL_CLASS_PASS,
HLSL_CLASS_PIXEL_SHADER,
HLSL_CLASS_RENDER_TARGET_VIEW,
HLSL_CLASS_SAMPLER,
HLSL_CLASS_STRING,
HLSL_CLASS_TECHNIQUE,
HLSL_CLASS_TEXTURE,
HLSL_CLASS_UAV,
HLSL_CLASS_VERTEX_SHADER,
HLSL_CLASS_VOID,
};
enum hlsl_base_type
@ -90,18 +101,6 @@ enum hlsl_base_type
HLSL_TYPE_UINT,
HLSL_TYPE_BOOL,
HLSL_TYPE_LAST_SCALAR = HLSL_TYPE_BOOL,
HLSL_TYPE_SAMPLER,
HLSL_TYPE_TEXTURE,
HLSL_TYPE_UAV,
HLSL_TYPE_PIXELSHADER,
HLSL_TYPE_VERTEXSHADER,
HLSL_TYPE_PASS,
HLSL_TYPE_RENDERTARGETVIEW,
HLSL_TYPE_DEPTHSTENCILVIEW,
HLSL_TYPE_TECHNIQUE,
HLSL_TYPE_EFFECT_GROUP,
HLSL_TYPE_STRING,
HLSL_TYPE_VOID,
};
enum hlsl_sampler_dim
@ -143,17 +142,11 @@ struct hlsl_type
struct rb_entry scope_entry;
enum hlsl_type_class class;
/* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR.
* If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR.
* If class is HLSL_CLASS_OBJECT and base_type is HLSL_TYPE_TECHNIQUE, additional version
* field is used to distinguish between technique types.
* Otherwise, base_type is not used. */
enum hlsl_base_type base_type;
/* If base_type is HLSL_TYPE_SAMPLER, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_SAMPLER.
* If base_type is HLSL_TYPE_TEXTURE, then sampler_dim can be any value of the enum except
/* If class is HLSL_CLASS_SAMPLER, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_SAMPLER.
* If class is HLSL_CLASS_TEXTURE, then sampler_dim can be any value of the enum except
* HLSL_SAMPLER_DIM_GENERIC and HLSL_SAMPLER_DIM_COMPARISON.
* If base_type is HLSL_TYPE_UAV, then sampler_dim must be one of HLSL_SAMPLER_DIM_1D,
* If class is HLSL_CLASS_UAV, then sampler_dim must be one of HLSL_SAMPLER_DIM_1D,
* HLSL_SAMPLER_DIM_2D, HLSL_SAMPLER_DIM_3D, HLSL_SAMPLER_DIM_1DARRAY, HLSL_SAMPLER_DIM_2DARRAY,
* HLSL_SAMPLER_DIM_BUFFER, or HLSL_SAMPLER_DIM_STRUCTURED_BUFFER.
* Otherwise, sampler_dim is not used */
@ -171,11 +164,7 @@ struct hlsl_type
* If type is HLSL_CLASS_MATRIX, then dimx is the number of columns, and dimy the number of rows.
* If type is HLSL_CLASS_ARRAY, then dimx and dimy have the same value as in the type of the array elements.
* If type is HLSL_CLASS_STRUCT, then dimx is the sum of (dimx * dimy) of every component, and dimy = 1.
* If type is HLSL_CLASS_OBJECT, dimx and dimy depend on the base_type:
* If base_type is HLSL_TYPE_SAMPLER, then both dimx = 1 and dimy = 1.
* If base_type is HLSL_TYPE_TEXTURE, then dimx = 4 and dimy = 1.
* If base_type is HLSL_TYPE_UAV, then dimx is the dimx of e.resource_format, and dimy = 1.
* Otherwise both dimx = 1 and dimy = 1. */
*/
unsigned int dimx;
unsigned int dimy;
/* Sample count for HLSL_SAMPLER_DIM_2DMS or HLSL_SAMPLER_DIM_2DMSARRAY. */
@ -183,6 +172,11 @@ struct hlsl_type
union
{
/* Additional information if type is numeric. */
struct
{
enum hlsl_base_type type;
} numeric;
/* Additional information if type is HLSL_CLASS_STRUCT. */
struct
{
@ -196,8 +190,8 @@ struct hlsl_type
/* Array length, or HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT if it is not known yet at parse time. */
unsigned int elements_count;
} array;
/* Additional information if the base_type is HLSL_TYPE_TEXTURE or
* HLSL_TYPE_UAV. */
/* Additional information if the class is HLSL_CLASS_TEXTURE or
* HLSL_CLASS_UAV. */
struct
{
/* Format of the data contained within the type. */
@ -298,6 +292,7 @@ enum hlsl_ir_node_type
HLSL_IR_STORE,
HLSL_IR_SWIZZLE,
HLSL_IR_SWITCH,
HLSL_IR_STATEBLOCK_CONSTANT,
};
/* Common data for every type of IR instruction node. */
@ -374,6 +369,8 @@ struct hlsl_attribute
#define HLSL_STORAGE_CENTROID 0x00004000
#define HLSL_STORAGE_NOPERSPECTIVE 0x00008000
#define HLSL_STORAGE_LINEAR 0x00010000
#define HLSL_MODIFIER_SINGLE 0x00020000
#define HLSL_MODIFIER_EXPORT 0x00040000
#define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \
HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \
@ -393,7 +390,7 @@ struct hlsl_attribute
struct hlsl_reg_reservation
{
char reg_type;
unsigned int reg_index;
unsigned int reg_space, reg_index;
char offset_type;
unsigned int offset_index;
@ -421,6 +418,14 @@ struct hlsl_ir_var
/* Scope that contains annotations for this variable. */
struct hlsl_scope *annotations;
/* A dynamic array containing the state block on the variable's declaration, if any.
* An array variable may contain multiple state blocks.
* A technique pass will always contain one.
* These are only really used for effect profiles. */
struct hlsl_state_block **state_blocks;
unsigned int state_block_count;
size_t state_block_capacity;
/* Indexes of the IR instructions where the variable is first written and last read (liveness
* range). The IR instructions are numerated starting from 2, because 0 means unused, and 1
* means function entry. */
@ -442,9 +447,10 @@ struct hlsl_ir_var
enum hlsl_sampler_dim sampler_dim;
struct vkd3d_shader_location first_sampler_dim_loc;
} *objects_usage[HLSL_REGSET_LAST_OBJECT + 1];
/* Minimum number of binds required to include all object components actually used in the shader.
* It may be less than the allocation size, e.g. for texture arrays. */
unsigned int bind_count[HLSL_REGSET_LAST_OBJECT + 1];
/* Minimum number of binds required to include all components actually used in the shader.
* It may be less than the allocation size, e.g. for texture arrays.
* The bind_count for HLSL_REGSET_NUMERIC is only used in uniforms for now. */
unsigned int bind_count[HLSL_REGSET_LAST + 1];
/* Whether the shader performs dereferences with non-constant offsets in the variable. */
bool indexable;
@ -456,6 +462,40 @@ struct hlsl_ir_var
uint32_t is_separated_resource : 1;
};
/* This struct is used to represent assignments in state block entries:
* name = {args[0], args[1], ...};
* - or -
* name = args[0]
* - or -
* name[lhs_index] = args[0]
* - or -
* name[lhs_index] = {args[0], args[1], ...};
*/
struct hlsl_state_block_entry
{
/* For assignments, the name in the lhs. */
char *name;
/* Resolved format-specific property identifier. */
unsigned int name_id;
/* Whether the lhs in the assignment is indexed and, in that case, its index. */
bool lhs_has_index;
unsigned int lhs_index;
/* Instructions present in the rhs. */
struct hlsl_block *instrs;
/* For assignments, arguments of the rhs initializer. */
struct hlsl_src *args;
unsigned int args_count;
};
struct hlsl_state_block
{
struct hlsl_state_block_entry **entries;
size_t count, capacity;
};
/* Sized array of variables representing a function's parameters. */
struct hlsl_func_parameters
{
@ -593,18 +633,15 @@ enum hlsl_ir_expr_op
HLSL_OP2_MUL,
HLSL_OP2_NEQUAL,
HLSL_OP2_RSHIFT,
/* SLT(a, b) retrieves 1.0 if (a < b), else 0.0. Only used for SM1-SM3 target vertex shaders. */
HLSL_OP2_SLT,
/* DP2ADD(a, b, c) computes the scalar product of a.xy and b.xy,
* then adds c. */
HLSL_OP3_DP2ADD,
/* MOVC(a, b, c) returns c if a is bitwise zero and b otherwise.
* TERNARY(a, b, c) returns c if a == 0 and b otherwise.
* They differ for floating point numbers, because
* -0.0 == 0.0, but it is not bitwise zero. CMP(a, b, c) returns b
if a >= 0, and c otherwise. It's used only for SM1-SM3 targets, while
SM4+ is using MOVC in such cases. */
/* TERNARY(a, b, c) returns 'b' if 'a' is true and 'c' otherwise. 'a' must always be boolean.
* CMP(a, b, c) returns 'b' if 'a' >= 0, and 'c' otherwise. It's used only for SM1-SM3 targets. */
HLSL_OP3_CMP,
HLSL_OP3_MOVC,
HLSL_OP3_TERNARY,
};
@ -750,6 +787,14 @@ struct hlsl_ir_constant
struct hlsl_reg reg;
};
/* Stateblock constants are undeclared values found on state blocks or technique passes descriptions,
* that do not concern regular pixel, vertex, or compute shaders, except for parsing. */
struct hlsl_ir_stateblock_constant
{
struct hlsl_ir_node node;
char *name;
};
struct hlsl_scope
{
/* Item entry for hlsl_ctx.scopes. */
@ -798,10 +843,13 @@ struct hlsl_buffer
struct vkd3d_shader_location loc;
enum hlsl_buffer_type type;
const char *name;
uint32_t modifiers;
/* Register reserved for this buffer, if any.
* If provided, it should be of type 'b' if type is HLSL_BUFFER_CONSTANT and 't' if type is
* HLSL_BUFFER_TEXTURE. */
struct hlsl_reg_reservation reservation;
/* Scope that contains annotations for this buffer. */
struct hlsl_scope *annotations;
/* Item entry for hlsl_ctx.buffers */
struct list entry;
@ -920,8 +968,21 @@ struct hlsl_ctx
uint32_t found_numthreads : 1;
bool semantic_compat_mapping;
bool child_effect;
bool include_empty_buffers;
bool warn_implicit_truncation;
};
static inline bool hlsl_version_ge(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor)
{
return ctx->profile->major_version > major || (ctx->profile->major_version == major && ctx->profile->minor_version >= minor);
}
static inline bool hlsl_version_lt(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor)
{
return !hlsl_version_ge(ctx, major, minor);
}
struct hlsl_resource_load_params
{
struct hlsl_type *format;
@ -1009,6 +1070,12 @@ static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *n
return CONTAINING_RECORD(node, struct hlsl_ir_switch, node);
}
static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(const struct hlsl_ir_node *node)
{
assert(node->type == HLSL_IR_STATEBLOCK_CONSTANT);
return CONTAINING_RECORD(node, struct hlsl_ir_stateblock_constant, node);
}
static inline void hlsl_block_init(struct hlsl_block *block)
{
list_init(&block->instrs);
@ -1183,6 +1250,7 @@ bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const
void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func);
void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body);
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);
int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out);
@ -1201,6 +1269,7 @@ void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
void hlsl_free_attribute(struct hlsl_attribute *attr);
void hlsl_free_instr(struct hlsl_ir_node *node);
void hlsl_free_instr_list(struct list *list);
void hlsl_free_state_block(struct hlsl_state_block *state_block);
void hlsl_free_type(struct hlsl_type *type);
void hlsl_free_var(struct hlsl_ir_var *decl);
@ -1222,7 +1291,8 @@ struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_exp
struct hlsl_ir_node *arg2);
struct hlsl_ir_node *hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc);
struct hlsl_buffer *hlsl_new_buffer(struct hlsl_ctx *ctx, enum hlsl_buffer_type type, const char *name,
const struct hlsl_reg_reservation *reservation, const struct vkd3d_shader_location *loc);
uint32_t modifiers, const struct hlsl_reg_reservation *reservation, struct hlsl_scope *annotations,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *decl,
const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_cast(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_type *type,
@ -1243,6 +1313,8 @@ struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *cond
struct hlsl_ir_node *hlsl_new_int_constant(struct hlsl_ctx *ctx, int32_t n, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_jump(struct hlsl_ctx *ctx,
enum hlsl_ir_jump_type type, struct hlsl_ir_node *condition, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op,
struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, struct hlsl_ir_node *arg3);
void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var);
@ -1279,6 +1351,8 @@ struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name,
struct hlsl_struct_field *fields, size_t field_count);
struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components,
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name,
struct vkd3d_shader_location *loc);
struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template,
struct hlsl_type *type, const struct vkd3d_shader_location *loc);
struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const char *name,
@ -1330,7 +1404,6 @@ unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);
void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx);
void hlsl_prepend_global_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block);
const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type);
unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type);
@ -1352,10 +1425,13 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere
bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *block);
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
struct hlsl_block *block, void *context);
D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type);
D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type);
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);

View File

@ -76,6 +76,7 @@ case {return KW_CASE; }
cbuffer {return KW_CBUFFER; }
centroid {return KW_CENTROID; }
column_major {return KW_COLUMN_MAJOR; }
ComputeShader {return KW_COMPUTESHADER; }
compile {return KW_COMPILE; }
const {return KW_CONST; }
continue {return KW_CONTINUE; }
@ -83,15 +84,18 @@ DepthStencilState {return KW_DEPTHSTENCILSTATE; }
DepthStencilView {return KW_DEPTHSTENCILVIEW; }
default {return KW_DEFAULT; }
discard {return KW_DISCARD; }
DomainShader {return KW_DOMAINSHADER; }
do {return KW_DO; }
double {return KW_DOUBLE; }
else {return KW_ELSE; }
export {return KW_EXPORT; }
extern {return KW_EXTERN; }
false {return KW_FALSE; }
for {return KW_FOR; }
fxgroup {return KW_FXGROUP; }
GeometryShader {return KW_GEOMETRYSHADER; }
groupshared {return KW_GROUPSHARED; }
HullShader {return KW_HULLSHADER; }
if {return KW_IF; }
in {return KW_IN; }
inline {return KW_INLINE; }
@ -105,7 +109,7 @@ out {return KW_OUT; }
packoffset {return KW_PACKOFFSET; }
pass {return KW_PASS; }
PixelShader {return KW_PIXELSHADER; }
precise {return KW_PRECISE; }
pixelshader {return KW_PIXELSHADER; }
RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; }
RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; }
RasterizerOrderedTexture1D {return KW_RASTERIZERORDEREDTEXTURE1D; }
@ -163,6 +167,7 @@ typedef {return KW_TYPEDEF; }
uniform {return KW_UNIFORM; }
vector {return KW_VECTOR; }
VertexShader {return KW_VERTEXSHADER; }
vertexshader {return KW_VERTEXSHADER; }
void {return KW_VOID; }
volatile {return KW_VOLATILE; }
while {return KW_WHILE; }
@ -186,7 +191,7 @@ while {return KW_WHILE; }
%= {return OP_MODASSIGN; }
&= {return OP_ANDASSIGN; }
\|= {return OP_ORASSIGN; }
^= {return OP_XORASSIGN; }
\^= {return OP_XORASSIGN; }
{IDENTIFIER} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,10 +25,10 @@
static bool fold_abs(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -116,10 +116,10 @@ static int32_t double_to_int(double x)
static bool fold_bit_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -158,7 +158,7 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src->node.data_type->base_type)
switch (src->node.data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -200,7 +200,7 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
vkd3d_unreachable();
}
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -231,10 +231,10 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -257,10 +257,10 @@ static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -283,10 +283,10 @@ static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_floor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -309,11 +309,11 @@ static bool fold_floor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_fract(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
float i;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -336,10 +336,10 @@ static bool fold_fract(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_log2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -381,10 +381,10 @@ static bool fold_log2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con
static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -415,10 +415,10 @@ static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -439,10 +439,10 @@ static bool fold_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -484,10 +484,10 @@ static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_rsq(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -524,10 +524,10 @@ static bool fold_rsq(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -550,10 +550,10 @@ static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src->node.data_type->base_type);
assert(type == src->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -595,11 +595,11 @@ static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con
static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -632,11 +632,11 @@ static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_and(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -659,11 +659,11 @@ static bool fold_and(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_or(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -686,11 +686,11 @@ static bool fold_or(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const
static bool fold_bit_xor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -712,11 +712,11 @@ static bool fold_bit_xor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
static bool fold_dot(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
assert(src1->node.data_type->dimx == src2->node.data_type->dimx);
dst->u[0].f = 0.0f;
@ -740,12 +740,12 @@ static bool fold_dot(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_dp2add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2, const struct hlsl_ir_constant *src3)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src3->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
assert(type == src3->node.data_type->e.numeric.type);
assert(src1->node.data_type->dimx == src2->node.data_type->dimx);
assert(src3->node.data_type->dimx == 1);
@ -771,11 +771,11 @@ static bool fold_div(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2,
const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -841,12 +841,12 @@ static bool fold_equal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, co
{
unsigned int k;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->base_type == src2->node.data_type->base_type);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -877,12 +877,12 @@ static bool fold_gequal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
{
unsigned int k;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->base_type == src2->node.data_type->base_type);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -916,12 +916,12 @@ static bool fold_less(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con
{
unsigned int k;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->base_type == src2->node.data_type->base_type);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -955,14 +955,14 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
{
unsigned int k;
assert(dst_type->base_type == src1->node.data_type->base_type);
assert(src2->node.data_type->base_type == HLSL_TYPE_INT);
assert(dst_type->e.numeric.type == src1->node.data_type->e.numeric.type);
assert(src2->node.data_type->e.numeric.type == HLSL_TYPE_INT);
for (k = 0; k < dst_type->dimx; ++k)
{
unsigned int shift = src2->value.u[k].u % 32;
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_INT:
dst->u[k].i = src1->value.u[k].i << shift;
@ -983,11 +983,11 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
static bool fold_max(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -1021,11 +1021,11 @@ static bool fold_max(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_min(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -1060,11 +1060,11 @@ static bool fold_mod(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2,
const struct vkd3d_shader_location *loc)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -1102,11 +1102,11 @@ static bool fold_mod(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons
static bool fold_mul(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type,
const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2)
{
enum hlsl_base_type type = dst_type->base_type;
enum hlsl_base_type type = dst_type->e.numeric.type;
unsigned int k;
assert(type == src1->node.data_type->base_type);
assert(type == src2->node.data_type->base_type);
assert(type == src1->node.data_type->e.numeric.type);
assert(type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
@ -1139,12 +1139,12 @@ static bool fold_nequal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
{
unsigned int k;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->base_type == src2->node.data_type->base_type);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type);
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -1175,32 +1175,13 @@ static bool fold_ternary(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
{
unsigned int k;
assert(dst_type->base_type == src2->node.data_type->base_type);
assert(dst_type->base_type == src3->node.data_type->base_type);
assert(dst_type->e.numeric.type == src2->node.data_type->e.numeric.type);
assert(dst_type->e.numeric.type == src3->node.data_type->e.numeric.type);
assert(src1->node.data_type->e.numeric.type == HLSL_TYPE_BOOL);
for (k = 0; k < dst_type->dimx; ++k)
{
switch (src1->node.data_type->base_type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
dst->u[k] = src1->value.u[k].f != 0.0f ? src2->value.u[k] : src3->value.u[k];
break;
dst->u[k] = src1->value.u[k].u ? src2->value.u[k] : src3->value.u[k];
case HLSL_TYPE_DOUBLE:
dst->u[k] = src1->value.u[k].d != 0.0 ? src2->value.u[k] : src3->value.u[k];
break;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
case HLSL_TYPE_BOOL:
dst->u[k] = src1->value.u[k].u ? src2->value.u[k] : src3->value.u[k];
break;
default:
vkd3d_unreachable();
}
}
return true;
}
@ -1209,14 +1190,14 @@ static bool fold_rshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c
{
unsigned int k;
assert(dst_type->base_type == src1->node.data_type->base_type);
assert(src2->node.data_type->base_type == HLSL_TYPE_INT);
assert(dst_type->e.numeric.type == src1->node.data_type->e.numeric.type);
assert(src2->node.data_type->e.numeric.type == HLSL_TYPE_INT);
for (k = 0; k < dst_type->dimx; ++k)
{
unsigned int shift = src2->value.u[k].u % 32;
switch (src1->node.data_type->base_type)
switch (src1->node.data_type->e.numeric.type)
{
case HLSL_TYPE_INT:
dst->u[k].i = src1->value.u[k].i >> shift;
@ -1415,6 +1396,136 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
return success;
}
static bool constant_is_zero(struct hlsl_ir_constant *const_arg)
{
struct hlsl_type *data_type = const_arg->node.data_type;
unsigned int k;
for (k = 0; k < data_type->dimx; ++k)
{
switch (data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
if (const_arg->value.u[k].f != 0.0f)
return false;
break;
case HLSL_TYPE_DOUBLE:
if (const_arg->value.u[k].d != 0.0)
return false;
break;
case HLSL_TYPE_UINT:
case HLSL_TYPE_INT:
case HLSL_TYPE_BOOL:
if (const_arg->value.u[k].u != 0)
return false;
break;
default:
return false;
}
}
return true;
}
static bool constant_is_one(struct hlsl_ir_constant *const_arg)
{
struct hlsl_type *data_type = const_arg->node.data_type;
unsigned int k;
for (k = 0; k < data_type->dimx; ++k)
{
switch (data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
if (const_arg->value.u[k].f != 1.0f)
return false;
break;
case HLSL_TYPE_DOUBLE:
if (const_arg->value.u[k].d != 1.0)
return false;
break;
case HLSL_TYPE_UINT:
case HLSL_TYPE_INT:
case HLSL_TYPE_BOOL:
if (const_arg->value.u[k].u != 1)
return false;
break;
default:
return false;
}
}
return true;
}
bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_ir_constant *const_arg = NULL;
struct hlsl_ir_node *mut_arg = NULL;
struct hlsl_ir_node *res_node;
struct hlsl_ir_expr *expr;
unsigned int i;
if (instr->type != HLSL_IR_EXPR)
return false;
expr = hlsl_ir_expr(instr);
if (instr->data_type->class > HLSL_CLASS_VECTOR)
return false;
/* Verify that the expression has two operands. */
for (i = 0; i < ARRAY_SIZE(expr->operands); ++i)
{
if (!!expr->operands[i].node != (i < 2))
return false;
}
if (expr->operands[0].node->type == HLSL_IR_CONSTANT)
{
const_arg = hlsl_ir_constant(expr->operands[0].node);
mut_arg = expr->operands[1].node;
}
else if (expr->operands[1].node->type == HLSL_IR_CONSTANT)
{
mut_arg = expr->operands[0].node;
const_arg = hlsl_ir_constant(expr->operands[1].node);
}
else
{
return false;
}
res_node = NULL;
switch (expr->op)
{
case HLSL_OP2_ADD:
if (constant_is_zero(const_arg))
res_node = mut_arg;
break;
case HLSL_OP2_MUL:
if (constant_is_one(const_arg))
res_node = mut_arg;
break;
default:
break;
}
if (res_node)
{
hlsl_replace_node(&expr->node, res_node);
return true;
}
return false;
}
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
{
struct hlsl_constant_value value;

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,6 @@
%{
#include "preproc.h"
#include "preproc.tab.h"
#undef ERROR /* defined in wingdi.h */
@ -66,7 +65,7 @@ static void update_location(struct preproc_ctx *ctx);
%s LINE
NEWLINE \r?\n
WS [ \t]
WS [ \t\r]
IDENTIFIER [A-Za-z_][A-Za-z0-9_]*
INT_SUFFIX [uUlL]{0,2}

File diff suppressed because it is too large Load Diff

View File

@ -719,14 +719,9 @@ static const enum vkd3d_data_type data_type_table[] =
/* VKD3D_SM4_DATA_UNUSED */ VKD3D_DATA_UNUSED,
};
static struct vkd3d_shader_sm4_parser *vkd3d_shader_sm4_parser(struct vkd3d_shader_parser *parser)
{
return CONTAINING_RECORD(parser, struct vkd3d_shader_sm4_parser, p);
}
static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4)
{
const struct vkd3d_shader_version *version = &sm4->p.program.shader_version;
const struct vkd3d_shader_version *version = &sm4->p.program->shader_version;
return version->major >= 5 && version->minor >= 1;
}
@ -811,7 +806,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui
icb->element_count = icb_size / VKD3D_VEC4_SIZE;
icb->is_null = false;
memcpy(icb->data, tokens, sizeof(*tokens) * icb_size);
shader_instruction_array_add_icb(&priv->p.program.instructions, icb);
shader_instruction_array_add_icb(&priv->p.program->instructions, icb);
ins->declaration.icb = icb;
}
@ -933,6 +928,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range;
struct vsir_program *program = priv->p.program;
unsigned int i, register_idx, register_count;
const struct shader_signature *signature;
enum vkd3d_shader_register_type type;
@ -954,32 +950,32 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins
case VKD3DSPR_INCONTROLPOINT:
io_masks = priv->input_register_masks;
ranges = &priv->input_index_ranges;
signature = &priv->p.shader_desc.input_signature;
signature = &program->input_signature;
break;
case VKD3DSPR_OUTPUT:
if (sm4_parser_is_in_fork_or_join_phase(priv))
{
io_masks = priv->patch_constant_register_masks;
ranges = &priv->patch_constant_index_ranges;
signature = &priv->p.shader_desc.patch_constant_signature;
signature = &program->patch_constant_signature;
}
else
{
io_masks = priv->output_register_masks;
ranges = &priv->output_index_ranges;
signature = &priv->p.shader_desc.output_signature;
signature = &program->output_signature;
}
break;
case VKD3DSPR_COLOROUT:
case VKD3DSPR_OUTCONTROLPOINT:
io_masks = priv->output_register_masks;
ranges = &priv->output_index_ranges;
signature = &priv->p.shader_desc.output_signature;
signature = &program->output_signature;
break;
case VKD3DSPR_PATCHCONST:
io_masks = priv->patch_constant_register_masks;
ranges = &priv->patch_constant_index_ranges;
signature = &priv->p.shader_desc.patch_constant_signature;
signature = &program->patch_constant_signature;
break;
default:
@ -1057,16 +1053,17 @@ static void shader_sm4_read_dcl_output_topology(struct vkd3d_shader_instruction
}
static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *sm4)
{
enum vkd3d_sm4_input_primitive_type primitive_type;
struct vsir_program *program = sm4->p.program;
primitive_type = (opcode_token & VKD3D_SM4_PRIMITIVE_TYPE_MASK) >> VKD3D_SM4_PRIMITIVE_TYPE_SHIFT;
if (VKD3D_SM5_INPUT_PT_PATCH1 <= primitive_type && primitive_type <= VKD3D_SM5_INPUT_PT_PATCH32)
{
ins->declaration.primitive_type.type = VKD3D_PT_PATCH;
ins->declaration.primitive_type.patch_vertex_count = primitive_type - VKD3D_SM5_INPUT_PT_PATCH1 + 1;
priv->p.program.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count;
program->input_control_point_count = ins->declaration.primitive_type.patch_vertex_count;
}
else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table))
{
@ -1075,7 +1072,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
else
{
ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type].vkd3d_type;
priv->p.program.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count;
program->input_control_point_count = input_primitive_type_table[primitive_type].control_point_count;
}
if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED)
@ -1083,11 +1080,13 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
}
static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *sm4)
{
struct vsir_program *program = sm4->p.program;
ins->declaration.count = *tokens;
if (opcode == VKD3D_SM4_OP_DCL_TEMPS)
priv->p.program.temp_count = max(priv->p.program.temp_count, *tokens);
program->temp_count = max(program->temp_count, *tokens);
}
static void shader_sm4_read_declaration_dst(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@ -1113,7 +1112,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u
if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
{
struct signature_element *e = vsir_signature_find_element_for_reg(
&priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
&priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
e->interpolation_mode = ins->flags;
}
@ -1128,7 +1127,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in
if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
{
struct signature_element *e = vsir_signature_find_element_for_reg(
&priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
&priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
e->interpolation_mode = ins->flags;
}
@ -1183,15 +1182,17 @@ static void shader_sm5_read_dcl_interface(struct vkd3d_shader_instruction *ins,
}
static void shader_sm5_read_control_point_count(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *sm4)
{
struct vsir_program *program = sm4->p.program;
ins->declaration.count = (opcode_token & VKD3D_SM5_CONTROL_POINT_COUNT_MASK)
>> VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT;
if (opcode == VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT)
priv->p.program.input_control_point_count = ins->declaration.count;
program->input_control_point_count = ins->declaration.count;
else
priv->p.program.output_control_point_count = ins->declaration.count;
program->output_control_point_count = ins->declaration.count;
}
static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@ -1263,6 +1264,7 @@ static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins, u
ins->declaration.tgsm_raw.byte_count = *tokens;
if (ins->declaration.tgsm_raw.byte_count % 4)
FIXME("Byte count %u is not multiple of 4.\n", ins->declaration.tgsm_raw.byte_count);
ins->declaration.tgsm_raw.zero_init = false;
}
static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@ -1274,6 +1276,7 @@ static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction
ins->declaration.tgsm_structured.structure_count = *tokens;
if (ins->declaration.tgsm_structured.byte_stride % 4)
FIXME("Byte stride %u is not multiple of 4.\n", ins->declaration.tgsm_structured.byte_stride);
ins->declaration.tgsm_structured.zero_init = false;
}
static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@ -1743,21 +1746,12 @@ static enum vkd3d_data_type map_data_type(char t)
}
}
static void shader_sm4_destroy(struct vkd3d_shader_parser *parser)
{
struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser);
vsir_program_cleanup(&parser->program);
free_shader_desc(&parser->shader_desc);
vkd3d_free(sm4);
}
static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
const uint32_t *end, uint32_t addressing, struct vkd3d_shader_register_index *reg_idx)
{
if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE)
{
struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(&priv->p.program, 1);
struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(priv->p.program, 1);
if (!(reg_idx->rel_addr = rel_addr))
{
@ -2035,7 +2029,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register *
{
return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT
|| (reg->type == VKD3DSPR_INPUT && (priv->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE
|| priv->p.program.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY));
|| priv->p.program->shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY));
}
static uint32_t mask_from_swizzle(uint32_t swizzle)
@ -2359,7 +2353,7 @@ static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d
static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, struct vkd3d_shader_instruction *ins)
{
const struct vkd3d_sm4_opcode_info *opcode_info;
struct vsir_program *program = &sm4->p.program;
struct vsir_program *program = sm4->p.program;
uint32_t opcode_token, opcode, previous_token;
struct vkd3d_shader_dst_param *dst_params;
struct vkd3d_shader_src_param *src_params;
@ -2498,13 +2492,8 @@ fail:
return;
}
static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
{
.parser_destroy = shader_sm4_destroy,
};
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code,
size_t byte_code_size, const char *source_name, const struct shader_signature *output_signature,
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_program *program,
const uint32_t *byte_code, size_t byte_code_size, const char *source_name,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_version version;
@ -2563,9 +2552,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops,
token_count / 7u + 20))
if (!vsir_program_init(program, &version, token_count / 7u + 20))
return false;
vkd3d_shader_parser_init(&sm4->p, program, message_context, source_name);
sm4->ptr = sm4->start;
init_sm4_lookup_tables(&sm4->lookup);
@ -2644,94 +2633,88 @@ static void shader_sm4_validate_default_phase_index_ranges(struct vkd3d_shader_s
return;
}
int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program)
{
struct vkd3d_shader_instruction_array *instructions;
struct vkd3d_shader_desc *shader_desc;
struct vkd3d_shader_sm4_parser sm4 = {0};
struct dxbc_shader_desc dxbc_desc = {0};
struct vkd3d_shader_instruction *ins;
struct vkd3d_shader_sm4_parser *sm4;
int ret;
if (!(sm4 = vkd3d_calloc(1, sizeof(*sm4))))
{
ERR("Failed to allocate parser.\n");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
shader_desc = &sm4->p.shader_desc;
shader_desc->is_dxil = false;
dxbc_desc.is_dxil = false;
if ((ret = shader_extract_from_dxbc(&compile_info->source,
message_context, compile_info->source_name, shader_desc)) < 0)
message_context, compile_info->source_name, &dxbc_desc)) < 0)
{
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
vkd3d_free(sm4);
return ret;
}
if (!shader_sm4_init(sm4, shader_desc->byte_code, shader_desc->byte_code_size,
compile_info->source_name, &shader_desc->output_signature, message_context))
if (!shader_sm4_init(&sm4, program, dxbc_desc.byte_code, dxbc_desc.byte_code_size,
compile_info->source_name, message_context))
{
WARN("Failed to initialise shader parser.\n");
free_shader_desc(shader_desc);
vkd3d_free(sm4);
free_dxbc_shader_desc(&dxbc_desc);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
program->input_signature = dxbc_desc.input_signature;
program->output_signature = dxbc_desc.output_signature;
program->patch_constant_signature = dxbc_desc.patch_constant_signature;
memset(&dxbc_desc, 0, sizeof(dxbc_desc));
/* DXBC stores used masks inverted for output signatures, for some reason.
* We return them un-inverted. */
uninvert_used_masks(&shader_desc->output_signature);
if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL)
uninvert_used_masks(&shader_desc->patch_constant_signature);
uninvert_used_masks(&program->output_signature);
if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL)
uninvert_used_masks(&program->patch_constant_signature);
if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature,
sm4->input_register_masks, "Input")
|| !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature,
sm4->output_register_masks, "Output")
|| !shader_sm4_parser_validate_signature(sm4, &shader_desc->patch_constant_signature,
sm4->patch_constant_register_masks, "Patch constant"))
if (!shader_sm4_parser_validate_signature(&sm4, &program->input_signature,
sm4.input_register_masks, "Input")
|| !shader_sm4_parser_validate_signature(&sm4, &program->output_signature,
sm4.output_register_masks, "Output")
|| !shader_sm4_parser_validate_signature(&sm4, &program->patch_constant_signature,
sm4.patch_constant_register_masks, "Patch constant"))
{
shader_sm4_destroy(&sm4->p);
vsir_program_cleanup(program);
return VKD3D_ERROR_INVALID_SHADER;
}
instructions = &sm4->p.program.instructions;
while (sm4->ptr != sm4->end)
instructions = &program->instructions;
while (sm4.ptr != sm4.end)
{
if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
{
ERR("Failed to allocate instructions.\n");
vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
shader_sm4_destroy(&sm4->p);
vkd3d_shader_parser_error(&sm4.p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory.");
vsir_program_cleanup(program);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
ins = &instructions->elements[instructions->count];
shader_sm4_read_instruction(sm4, ins);
shader_sm4_read_instruction(&sm4, ins);
if (ins->handler_idx == VKD3DSIH_INVALID)
{
WARN("Encountered unrecognized or invalid instruction.\n");
shader_sm4_destroy(&sm4->p);
vsir_program_cleanup(program);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
++instructions->count;
}
if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL
&& !sm4->has_control_point_phase && !sm4->p.failed)
shader_sm4_validate_default_phase_index_ranges(sm4);
if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL
&& !sm4.has_control_point_phase && !sm4.p.failed)
shader_sm4_validate_default_phase_index_ranges(&sm4);
if (!sm4->p.failed)
vsir_validate(&sm4->p);
if (!sm4.p.failed)
vkd3d_shader_parser_validate(&sm4.p, config_flags);
if (sm4->p.failed)
if (sm4.p.failed)
{
WARN("Failed to parse shader.\n");
shader_sm4_destroy(&sm4->p);
vsir_program_cleanup(program);
return VKD3D_ERROR_INVALID_SHADER;
}
*parser = &sm4->p;
return VKD3D_OK;
}
@ -2739,7 +2722,7 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc
static bool type_is_integer(const struct hlsl_type *type)
{
switch (type->base_type)
switch (type->e.numeric.type)
{
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
@ -2928,7 +2911,7 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc,
put_u32(&buffer, 0); /* name */
put_u32(&buffer, usage_idx);
put_u32(&buffer, usage);
switch (var->data_type->base_type)
switch (var->data_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
case HLSL_TYPE_HALF:
@ -2989,31 +2972,39 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type)
{
switch (type->class)
{
case HLSL_CLASS_ARRAY:
return sm4_class(type->e.array.type);
case HLSL_CLASS_MATRIX:
assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK);
if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR)
return D3D_SVC_MATRIX_COLUMNS;
else
return D3D_SVC_MATRIX_ROWS;
case HLSL_CLASS_OBJECT:
return D3D_SVC_OBJECT;
case HLSL_CLASS_SCALAR:
return D3D_SVC_SCALAR;
case HLSL_CLASS_STRUCT:
return D3D_SVC_STRUCT;
case HLSL_CLASS_VECTOR:
return D3D_SVC_VECTOR;
default:
ERR("Invalid class %#x.\n", type->class);
vkd3d_unreachable();
case HLSL_CLASS_ARRAY:
case HLSL_CLASS_DEPTH_STENCIL_VIEW:
case HLSL_CLASS_EFFECT_GROUP:
case HLSL_CLASS_STRUCT:
case HLSL_CLASS_PASS:
case HLSL_CLASS_PIXEL_SHADER:
case HLSL_CLASS_RENDER_TARGET_VIEW:
case HLSL_CLASS_SAMPLER:
case HLSL_CLASS_STRING:
case HLSL_CLASS_TECHNIQUE:
case HLSL_CLASS_TEXTURE:
case HLSL_CLASS_UAV:
case HLSL_CLASS_VERTEX_SHADER:
case HLSL_CLASS_VOID:
break;
}
vkd3d_unreachable();
}
static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type)
{
switch (type->base_type)
switch (type->e.numeric.type)
{
case HLSL_TYPE_BOOL:
return D3D_SVT_BOOL;
@ -3024,68 +3015,8 @@ static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type)
return D3D_SVT_FLOAT;
case HLSL_TYPE_INT:
return D3D_SVT_INT;
case HLSL_TYPE_PIXELSHADER:
return D3D_SVT_PIXELSHADER;
case HLSL_TYPE_SAMPLER:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
return D3D_SVT_SAMPLER1D;
case HLSL_SAMPLER_DIM_2D:
return D3D_SVT_SAMPLER2D;
case HLSL_SAMPLER_DIM_3D:
return D3D_SVT_SAMPLER3D;
case HLSL_SAMPLER_DIM_CUBE:
return D3D_SVT_SAMPLERCUBE;
case HLSL_SAMPLER_DIM_GENERIC:
return D3D_SVT_SAMPLER;
default:
vkd3d_unreachable();
}
break;
case HLSL_TYPE_STRING:
return D3D_SVT_STRING;
case HLSL_TYPE_TEXTURE:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
return D3D_SVT_TEXTURE1D;
case HLSL_SAMPLER_DIM_2D:
return D3D_SVT_TEXTURE2D;
case HLSL_SAMPLER_DIM_2DMS:
return D3D_SVT_TEXTURE2DMS;
case HLSL_SAMPLER_DIM_3D:
return D3D_SVT_TEXTURE3D;
case HLSL_SAMPLER_DIM_CUBE:
return D3D_SVT_TEXTURECUBE;
case HLSL_SAMPLER_DIM_GENERIC:
return D3D_SVT_TEXTURE;
default:
vkd3d_unreachable();
}
break;
case HLSL_TYPE_UINT:
return D3D_SVT_UINT;
case HLSL_TYPE_VERTEXSHADER:
return D3D_SVT_VERTEXSHADER;
case HLSL_TYPE_VOID:
return D3D_SVT_VOID;
case HLSL_TYPE_UAV:
switch (type->sampler_dim)
{
case HLSL_SAMPLER_DIM_1D:
return D3D_SVT_RWTEXTURE1D;
case HLSL_SAMPLER_DIM_2D:
return D3D_SVT_RWTEXTURE2D;
case HLSL_SAMPLER_DIM_3D:
return D3D_SVT_RWTEXTURE3D;
case HLSL_SAMPLER_DIM_1DARRAY:
return D3D_SVT_RWTEXTURE1DARRAY;
case HLSL_SAMPLER_DIM_2DARRAY:
return D3D_SVT_RWTEXTURE2DARRAY;
default:
vkd3d_unreachable();
}
default:
vkd3d_unreachable();
}
@ -3096,8 +3027,8 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type);
const char *name = array_type->name ? array_type->name : "<unnamed>";
const struct hlsl_profile_info *profile = ctx->profile;
unsigned int field_count = 0, array_size = 0;
size_t fields_offset = 0, name_offset = 0;
unsigned int array_size = 0;
size_t name_offset = 0;
size_t i;
if (type->bytecode_offset)
@ -3111,32 +3042,47 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
if (array_type->class == HLSL_CLASS_STRUCT)
{
field_count = array_type->e.record.field_count;
unsigned int field_count = 0;
size_t fields_offset = 0;
for (i = 0; i < field_count; ++i)
for (i = 0; i < array_type->e.record.field_count; ++i)
{
struct hlsl_struct_field *field = &array_type->e.record.fields[i];
if (!field->type->reg_size[HLSL_REGSET_NUMERIC])
continue;
field->name_bytecode_offset = put_string(buffer, field->name);
write_sm4_type(ctx, buffer, field->type);
++field_count;
}
fields_offset = bytecode_align(buffer);
for (i = 0; i < field_count; ++i)
for (i = 0; i < array_type->e.record.field_count; ++i)
{
struct hlsl_struct_field *field = &array_type->e.record.fields[i];
if (!field->type->reg_size[HLSL_REGSET_NUMERIC])
continue;
put_u32(buffer, field->name_bytecode_offset);
put_u32(buffer, field->type->bytecode_offset);
put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]);
put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC] * sizeof(float));
}
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(D3D_SVC_STRUCT, D3D_SVT_VOID));
put_u32(buffer, vkd3d_make_u32(1, hlsl_type_component_count(array_type)));
put_u32(buffer, vkd3d_make_u32(array_size, field_count));
put_u32(buffer, fields_offset);
}
else
{
assert(array_type->class <= HLSL_CLASS_LAST_NUMERIC);
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(array_type), sm4_base_type(array_type)));
put_u32(buffer, vkd3d_make_u32(array_type->dimy, array_type->dimx));
put_u32(buffer, vkd3d_make_u32(array_size, 0));
put_u32(buffer, 1);
}
type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm4_class(type), sm4_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);
if (profile->major_version >= 5)
{
@ -3150,20 +3096,21 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
static D3D_SHADER_INPUT_TYPE sm4_resource_type(const struct hlsl_type *type)
{
if (type->class == HLSL_CLASS_ARRAY)
return sm4_resource_type(type->e.array.type);
switch (type->base_type)
switch (type->class)
{
case HLSL_TYPE_SAMPLER:
case HLSL_CLASS_ARRAY:
return sm4_resource_type(type->e.array.type);
case HLSL_CLASS_SAMPLER:
return D3D_SIT_SAMPLER;
case HLSL_TYPE_TEXTURE:
case HLSL_CLASS_TEXTURE:
return D3D_SIT_TEXTURE;
case HLSL_TYPE_UAV:
case HLSL_CLASS_UAV:
return D3D_SIT_UAV_RWTYPED;
default:
vkd3d_unreachable();
break;
}
vkd3d_unreachable();
}
static D3D_RESOURCE_RETURN_TYPE sm4_resource_format(const struct hlsl_type *type)
@ -3171,7 +3118,7 @@ static D3D_RESOURCE_RETURN_TYPE sm4_resource_format(const struct hlsl_type *type
if (type->class == HLSL_CLASS_ARRAY)
return sm4_resource_format(type->e.array.type);
switch (type->e.resource.format->base_type)
switch (type->e.resource.format->e.numeric.type)
{
case HLSL_TYPE_DOUBLE:
return D3D_RETURN_TYPE_DOUBLE;
@ -3328,7 +3275,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
extern_resources[*count].name = name;
extern_resources[*count].data_type = component_type;
extern_resources[*count].is_user_packed = false;
extern_resources[*count].is_user_packed = !!var->reg_reservation.reg_type;
extern_resources[*count].regset = regset;
extern_resources[*count].id = var->regs[regset].id + regset_offset;
@ -3428,10 +3375,10 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
if (profile->major_version >= 5)
{
put_u32(&buffer, TAG_RD11);
put_u32(&buffer, hlsl_version_ge(ctx, 5, 1) ? TAG_RD11_REVERSE : TAG_RD11);
put_u32(&buffer, 15 * sizeof(uint32_t)); /* size of RDEF header including this header */
put_u32(&buffer, 6 * sizeof(uint32_t)); /* size of buffer desc */
put_u32(&buffer, 8 * sizeof(uint32_t)); /* size of binding desc */
put_u32(&buffer, (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t)); /* size of binding desc */
put_u32(&buffer, 10 * sizeof(uint32_t)); /* size of variable desc */
put_u32(&buffer, 9 * sizeof(uint32_t)); /* size of type desc */
put_u32(&buffer, 3 * sizeof(uint32_t)); /* size of member desc */
@ -3448,6 +3395,9 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
const struct extern_resource *resource = &extern_resources[i];
uint32_t flags = 0;
if (hlsl_version_ge(ctx, 5, 1))
hlsl_fixme(ctx, &resource->var->loc, "Shader model 5.1 resource reflection.");
if (resource->is_user_packed)
flags |= D3D_SIF_USERPACKED;
@ -3480,6 +3430,9 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
if (!cbuffer->reg.allocated)
continue;
if (hlsl_version_ge(ctx, 5, 1))
hlsl_fixme(ctx, &cbuffer->loc, "Shader model 5.1 resource reflection.");
if (cbuffer->reservation.reg_type)
flags |= D3D_SIF_USERPACKED;
@ -3523,8 +3476,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->is_uniform && var->buffer == cbuffer
&& var->data_type->class != HLSL_CLASS_OBJECT)
if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC])
++var_count;
}
@ -3558,8 +3510,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->is_uniform && var->buffer == cbuffer
&& var->data_type->class != HLSL_CLASS_OBJECT)
if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC])
{
uint32_t flags = 0;
@ -3586,8 +3537,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
j = 0;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (var->is_uniform && var->buffer == cbuffer
&& var->data_type->class != HLSL_CLASS_OBJECT)
if (var->is_uniform && var->buffer == cbuffer && var->data_type->reg_size[HLSL_REGSET_NUMERIC])
{
const unsigned int var_size = (profile->major_version >= 5 ? 10 : 6);
size_t var_offset = vars_start + j * var_size * sizeof(uint32_t);
@ -4598,7 +4548,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node
enum hlsl_sampler_dim dim)
{
const struct hlsl_type *resource_type = hlsl_deref_get_type(tpf->ctx, resource);
bool multisampled = resource_type->base_type == HLSL_TYPE_TEXTURE
bool multisampled = resource_type->class == HLSL_CLASS_TEXTURE
&& (resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY);
bool uav = (hlsl_deref_get_regset(tpf->ctx, resource) == HLSL_REGSET_UAVS);
unsigned int coords_writemask = VKD3DSP_WRITEMASK_ALL;
@ -4756,11 +4706,11 @@ static void write_sm4_sampleinfo(const struct tpf_writer *tpf, const struct hlsl
const struct hlsl_ir_node *dst = &load->node;
struct sm4_instruction instr;
assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT);
assert(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT);
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO;
if (dst->data_type->base_type == HLSL_TYPE_UINT)
if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT)
instr.extra_bits |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
sm4_dst_from_node(&instr.dsts[0], dst);
@ -4785,11 +4735,11 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir
return;
}
assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT);
assert(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT);
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_RESINFO;
if (dst->data_type->base_type == HLSL_TYPE_UINT)
if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT)
instr.extra_bits |= VKD3DSI_RESINFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT;
sm4_dst_from_node(&instr.dsts[0], dst);
@ -4804,7 +4754,7 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir
static bool type_is_float(const struct hlsl_type *type)
{
return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF;
return type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF;
}
static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct hlsl_ir_expr *expr,
@ -4841,11 +4791,11 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex
/* Narrowing casts were already lowered. */
assert(src_type->dimx == dst_type->dimx);
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
@ -4874,7 +4824,7 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_TYPE_INT:
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
@ -4900,7 +4850,7 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_TYPE_UINT:
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
@ -4970,7 +4920,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
switch (expr->op)
{
case HLSL_OP1_ABS:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3DSPSM_ABS);
@ -5051,12 +5001,12 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP1_LOGIC_NOT:
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_unary_op(tpf, VKD3D_SM4_OP_NOT, &expr->node, arg1, 0);
break;
case HLSL_OP1_NEG:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3DSPSM_NEG);
@ -5109,7 +5059,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_ADD:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ADD, &expr->node, arg1, arg2);
@ -5141,7 +5091,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_DIV:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_DIV, &expr->node, arg1, arg2);
@ -5157,7 +5107,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_DOT:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
switch (arg1->data_type->dimx)
@ -5189,9 +5139,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
{
const struct hlsl_type *src_type = arg1->data_type;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_EQ, &expr->node, arg1, arg2);
@ -5215,9 +5165,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
{
const struct hlsl_type *src_type = arg1->data_type;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_GE, &expr->node, arg1, arg2);
@ -5244,9 +5194,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
{
const struct hlsl_type *src_type = arg1->data_type;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_LT, &expr->node, arg1, arg2);
@ -5270,23 +5220,23 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
}
case HLSL_OP2_LOGIC_AND:
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2);
break;
case HLSL_OP2_LOGIC_OR:
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_OR, &expr->node, arg1, arg2);
break;
case HLSL_OP2_LSHIFT:
assert(type_is_integer(dst_type));
assert(dst_type->base_type != HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, VKD3D_SM4_OP_ISHL, &expr->node, arg1, arg2);
break;
case HLSL_OP2_MAX:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_MAX, &expr->node, arg1, arg2);
@ -5306,7 +5256,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_MIN:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_MIN, &expr->node, arg1, arg2);
@ -5326,7 +5276,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_MOD:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_UINT:
write_sm4_binary_op_with_two_destinations(tpf, VKD3D_SM4_OP_UDIV, &expr->node, 1, arg1, arg2);
@ -5338,7 +5288,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
break;
case HLSL_OP2_MUL:
switch (dst_type->base_type)
switch (dst_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_MUL, &expr->node, arg1, arg2);
@ -5360,9 +5310,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
{
const struct hlsl_type *src_type = arg1->data_type;
assert(dst_type->base_type == HLSL_TYPE_BOOL);
assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
switch (src_type->base_type)
switch (src_type->e.numeric.type)
{
case HLSL_TYPE_FLOAT:
write_sm4_binary_op(tpf, VKD3D_SM4_OP_NE, &expr->node, arg1, arg2);
@ -5384,12 +5334,12 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
case HLSL_OP2_RSHIFT:
assert(type_is_integer(dst_type));
assert(dst_type->base_type != HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, dst_type->base_type == HLSL_TYPE_INT ? VKD3D_SM4_OP_ISHR : VKD3D_SM4_OP_USHR,
assert(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
write_sm4_binary_op(tpf, dst_type->e.numeric.type == HLSL_TYPE_INT ? VKD3D_SM4_OP_ISHR : VKD3D_SM4_OP_USHR,
&expr->node, arg1, arg2);
break;
case HLSL_OP3_MOVC:
case HLSL_OP3_TERNARY:
write_sm4_ternary_op(tpf, VKD3D_SM4_OP_MOVC, &expr->node, arg1, arg2, arg3);
break;
@ -5445,7 +5395,8 @@ static void write_sm4_jump(const struct tpf_writer *tpf, const struct hlsl_ir_ju
case HLSL_IR_JUMP_DISCARD_NZ:
{
instr.opcode = VKD3D_SM4_OP_DISCARD | VKD3D_SM4_CONDITIONAL_NZ;
instr.opcode = VKD3D_SM4_OP_DISCARD;
instr.extra_bits = VKD3D_SM4_CONDITIONAL_NZ;
memset(&instr.srcs[0], 0, sizeof(*instr.srcs));
instr.src_count = 1;
@ -5486,7 +5437,7 @@ static void write_sm4_load(const struct tpf_writer *tpf, const struct hlsl_ir_lo
instr.dst_count = 1;
assert(hlsl_is_numeric_type(type));
if (type->base_type == HLSL_TYPE_BOOL && var_is_user_input(tpf->ctx, load->src.var))
if (type->e.numeric.type == HLSL_TYPE_BOOL && var_is_user_input(tpf->ctx, load->src.var))
{
struct hlsl_constant_value value;
@ -5746,18 +5697,12 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc
{
if (instr->data_type)
{
if (instr->data_type->class == HLSL_CLASS_MATRIX)
if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
{
hlsl_fixme(tpf->ctx, &instr->loc, "Matrix operations need to be lowered.");
hlsl_fixme(tpf->ctx, &instr->loc, "Class %#x should have been lowered or removed.",
instr->data_type->class);
break;
}
else if (instr->data_type->class == HLSL_CLASS_OBJECT)
{
hlsl_fixme(tpf->ctx, &instr->loc, "Object copy.");
break;
}
assert(instr->data_type->class == HLSL_CLASS_SCALAR || instr->data_type->class == HLSL_CLASS_VECTOR);
if (!instr->reg.allocated)
{
@ -5854,13 +5799,21 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry)
{
if (cbuffer->reg.allocated)
{
if (hlsl_version_ge(ctx, 5, 1))
hlsl_fixme(ctx, &cbuffer->loc, "Shader model 5.1 resource definition.");
write_sm4_dcl_constant_buffer(&tpf, cbuffer);
}
}
for (i = 0; i < extern_resources_count; ++i)
{
const struct extern_resource *resource = &extern_resources[i];
if (hlsl_version_ge(ctx, 5, 1))
hlsl_fixme(ctx, &resource->var->loc, "Shader model 5.1 resource declaration.");
if (resource->regset == HLSL_REGSET_SAMPLERS)
write_sm4_dcl_samplers(&tpf, resource);
else if (resource->regset == HLSL_REGSET_TEXTURES)

View File

@ -71,8 +71,16 @@ void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer)
void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer)
{
buffer->buffer[0] = '\0';
buffer->content_size = 0;
vkd3d_string_buffer_truncate(buffer, 0);
}
void vkd3d_string_buffer_truncate(struct vkd3d_string_buffer *buffer, size_t size)
{
if (size < buffer->content_size)
{
buffer->buffer[size] = '\0';
buffer->content_size = size;
}
}
static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc)
@ -224,6 +232,16 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *cache, struct
cache->buffers[cache->count++] = buffer;
}
void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer)
{
code->code = buffer->buffer;
code->size = buffer->content_size;
buffer->buffer = NULL;
buffer->buffer_size = 0;
buffer->content_size = 0;
}
void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context,
enum vkd3d_shader_log_level log_level)
{
@ -520,7 +538,7 @@ static const struct vkd3d_debug_option vkd3d_shader_config_options[] =
{"force_validation", VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION}, /* force validation of internal shader representations */
};
static uint64_t vkd3d_shader_init_config_flags(void)
uint64_t vkd3d_shader_init_config_flags(void)
{
uint64_t config_flags;
const char *config;
@ -534,18 +552,14 @@ static uint64_t vkd3d_shader_init_config_flags(void)
return config_flags;
}
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops,
unsigned int instruction_reserve)
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vsir_program *program,
struct vkd3d_shader_message_context *message_context, const char *source_name)
{
parser->message_context = message_context;
parser->location.source_name = source_name;
parser->location.line = 1;
parser->location.column = 0;
parser->ops = ops;
parser->config_flags = vkd3d_shader_init_config_flags();
return vsir_program_init(&parser->program, version, instruction_reserve);
parser->program = program;
}
void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
@ -641,7 +655,15 @@ static bool vkd3d_shader_signature_from_shader_signature(struct vkd3d_shader_sig
struct vkd3d_shader_signature_element *d = &signature->elements[i];
struct signature_element *e = &src->elements[i];
d->semantic_name = e->semantic_name;
if (!(d->semantic_name = vkd3d_strdup(e->semantic_name)))
{
for (unsigned int j = 0; j < i; ++j)
{
vkd3d_free((void *)signature->elements[j].semantic_name);
}
vkd3d_free(signature->elements);
return false;
}
d->semantic_index = e->semantic_index;
d->stream_index = e->stream_index;
d->sysval_semantic = e->sysval_semantic;
@ -1375,9 +1397,9 @@ static void vkd3d_shader_free_scan_descriptor_info1(struct vkd3d_shader_scan_des
vkd3d_free(scan_descriptor_info->descriptors);
}
static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info,
static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context,
struct vkd3d_shader_scan_descriptor_info1 *descriptor_info1, struct vkd3d_shader_parser *parser)
struct vkd3d_shader_scan_descriptor_info1 *descriptor_info1)
{
struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info;
struct vkd3d_shader_scan_descriptor_info1 local_descriptor_info1 = {0};
@ -1408,27 +1430,27 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
descriptor_info1 = &local_descriptor_info1;
}
vkd3d_shader_scan_context_init(&context, &parser->program.shader_version, compile_info,
vkd3d_shader_scan_context_init(&context, &program->shader_version, compile_info,
descriptor_info1, combined_sampler_info, message_context);
if (TRACE_ON())
vkd3d_shader_trace(&parser->program);
vkd3d_shader_trace(program);
for (i = 0; i < parser->program.instructions.count; ++i)
for (i = 0; i < program->instructions.count; ++i)
{
instruction = &parser->program.instructions.elements[i];
instruction = &program->instructions.elements[i];
if ((ret = vkd3d_shader_scan_instruction(&context, instruction)) < 0)
break;
}
for (i = 0; i < ARRAY_SIZE(parser->shader_desc.flat_constant_count); ++i)
for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i)
{
unsigned int size = parser->shader_desc.flat_constant_count[i].external;
struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i};
struct vkd3d_shader_register reg = {.idx[0].offset = i, .idx_count = 1};
unsigned int size = program->flat_constant_count[i];
struct vkd3d_shader_descriptor_info1 *d;
if (parser->shader_desc.flat_constant_count[i].external)
if (size)
{
if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, &reg,
&range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT)))
@ -1438,11 +1460,11 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
if (!ret && signature_info)
{
if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &parser->shader_desc.input_signature)
if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &program->input_signature)
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->output,
&parser->shader_desc.output_signature)
&program->output_signature)
|| !vkd3d_shader_signature_from_shader_signature(&signature_info->patch_constant,
&parser->shader_desc.patch_constant_signature))
&program->patch_constant_signature))
{
ret = VKD3D_ERROR_OUT_OF_MEMORY;
}
@ -1470,60 +1492,6 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
return ret;
}
static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = scan_with_parser(compile_info, message_context, NULL, parser);
vkd3d_shader_parser_destroy(parser);
return ret;
}
static int scan_d3dbc(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm1_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = scan_with_parser(compile_info, message_context, NULL, parser);
vkd3d_shader_parser_destroy(parser);
return ret;
}
static int scan_dxil(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm6_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = scan_with_parser(compile_info, message_context, NULL, parser);
vkd3d_shader_parser_destroy(parser);
return ret;
}
int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages)
{
struct vkd3d_shader_message_context message_context;
@ -1543,29 +1511,45 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
vkd3d_shader_dump_shader(compile_info);
switch (compile_info->source_type)
if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL)
{
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = scan_dxbc(compile_info, &message_context);
break;
FIXME("HLSL support not implemented.\n");
ret = VKD3D_ERROR_NOT_IMPLEMENTED;
}
else
{
uint64_t config_flags = vkd3d_shader_init_config_flags();
struct vsir_program program;
case VKD3D_SHADER_SOURCE_HLSL:
FIXME("HLSL support not implemented.\n");
ret = VKD3D_ERROR_NOT_IMPLEMENTED;
break;
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = d3dbc_parse(compile_info, config_flags, &message_context, &program);
break;
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = scan_d3dbc(compile_info, &message_context);
break;
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = tpf_parse(compile_info, config_flags, &message_context, &program);
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
ret = scan_dxil(compile_info, &message_context);
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
ret = dxil_parse(compile_info, config_flags, &message_context, &program);
break;
default:
ERR("Unsupported source type %#x.\n", compile_info->source_type);
ret = VKD3D_ERROR_INVALID_ARGUMENT;
break;
default:
ERR("Unsupported source type %#x.\n", compile_info->source_type);
ret = VKD3D_ERROR_INVALID_ARGUMENT;
break;
}
if (ret < 0)
{
WARN("Failed to parse shader.\n");
}
else
{
ret = vsir_program_scan(&program, compile_info, &message_context, NULL);
vsir_program_cleanup(&program);
}
}
vkd3d_shader_message_context_trace_messages(&message_context);
@ -1575,12 +1559,11 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
return ret;
}
static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info;
struct vkd3d_glsl_generator *glsl_generator;
struct vkd3d_shader_compile_info scan_info;
int ret;
@ -1589,30 +1572,22 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
switch (compile_info->target_type)
{
case VKD3D_SHADER_TARGET_D3D_ASM:
ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_D3D);
ret = d3d_asm_compile(program, compile_info, out, VSIR_ASM_FLAG_NONE);
break;
case VKD3D_SHADER_TARGET_GLSL:
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0)
return ret;
if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->program.shader_version,
message_context, &parser->location)))
{
ERR("Failed to create GLSL generator.\n");
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
return VKD3D_ERROR;
}
ret = vkd3d_glsl_generator_generate(glsl_generator, &parser->program, out);
vkd3d_glsl_generator_destroy(glsl_generator);
ret = glsl_compile(program, config_flags, compile_info, out, message_context);
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
case VKD3D_SHADER_TARGET_SPIRV_BINARY:
case VKD3D_SHADER_TARGET_SPIRV_TEXT:
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0)
return ret;
ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context);
ret = spirv_compile(program, config_flags, &scan_descriptor_info,
compile_info, out, message_context);
vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
@ -1624,24 +1599,6 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
return ret;
}
static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context);
vkd3d_shader_parser_destroy(parser);
return ret;
}
static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
@ -1657,42 +1614,6 @@ static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info,
return ret;
}
static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm1_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context);
vkd3d_shader_parser_destroy(parser);
return ret;
}
static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_parser *parser;
int ret;
if ((ret = vkd3d_shader_sm6_parser_create(compile_info, message_context, &parser)) < 0)
{
WARN("Failed to initialise shader parser.\n");
return ret;
}
ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context);
vkd3d_shader_parser_destroy(parser);
return ret;
}
int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, char **messages)
{
@ -1713,26 +1634,44 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_shader_dump_shader(compile_info);
switch (compile_info->source_type)
if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL)
{
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = compile_dxbc_tpf(compile_info, out, &message_context);
break;
ret = compile_hlsl(compile_info, out, &message_context);
}
else
{
uint64_t config_flags = vkd3d_shader_init_config_flags();
struct vsir_program program;
case VKD3D_SHADER_SOURCE_HLSL:
ret = compile_hlsl(compile_info, out, &message_context);
break;
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = d3dbc_parse(compile_info, config_flags, &message_context, &program);
break;
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = compile_d3d_bytecode(compile_info, out, &message_context);
break;
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = tpf_parse(compile_info, config_flags, &message_context, &program);
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
ret = compile_dxbc_dxil(compile_info, out, &message_context);
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
ret = dxil_parse(compile_info, config_flags, &message_context, &program);
break;
default:
vkd3d_unreachable();
default:
ERR("Unsupported source type %#x.\n", compile_info->source_type);
ret = VKD3D_ERROR_INVALID_ARGUMENT;
break;
}
if (ret < 0)
{
WARN("Failed to parse shader.\n");
}
else
{
ret = vsir_program_compile(&program, config_flags, compile_info, out, &message_context);
vsir_program_cleanup(&program);
}
}
vkd3d_shader_message_context_trace_messages(&message_context);
@ -1830,6 +1769,10 @@ void vkd3d_shader_free_root_signature(struct vkd3d_shader_versioned_root_signatu
void shader_signature_cleanup(struct shader_signature *signature)
{
for (unsigned int i = 0; i < signature->element_count; ++i)
{
vkd3d_free((void *)signature->elements[i].semantic_name);
}
vkd3d_free(signature->elements);
signature->elements = NULL;
}
@ -1887,6 +1830,10 @@ void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature
{
TRACE("signature %p.\n", signature);
for (unsigned int i = 0; i < signature->element_count; ++i)
{
vkd3d_free((void *)signature->elements[i].semantic_name);
}
vkd3d_free(signature->elements);
signature->elements = NULL;
}
@ -1937,13 +1884,18 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
VKD3D_SHADER_TARGET_SPIRV_TEXT,
#endif
VKD3D_SHADER_TARGET_D3D_ASM,
#if 0
#ifdef VKD3D_SHADER_UNSUPPORTED_GLSL
VKD3D_SHADER_TARGET_GLSL,
#endif
};
static const enum vkd3d_shader_target_type hlsl_types[] =
{
VKD3D_SHADER_TARGET_SPIRV_BINARY,
#ifdef HAVE_SPIRV_TOOLS
VKD3D_SHADER_TARGET_SPIRV_TEXT,
#endif
VKD3D_SHADER_TARGET_D3D_ASM,
VKD3D_SHADER_TARGET_D3D_BYTECODE,
VKD3D_SHADER_TARGET_DXBC_TPF,
VKD3D_SHADER_TARGET_FX,
@ -1958,13 +1910,21 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
VKD3D_SHADER_TARGET_D3D_ASM,
};
#ifdef VKD3D_SHADER_UNSUPPORTED_DXIL
static const enum vkd3d_shader_target_type dxbc_dxil_types[] =
{
VKD3D_SHADER_TARGET_SPIRV_BINARY,
# ifdef HAVE_SPIRV_TOOLS
VKD3D_SHADER_TARGET_SPIRV_TEXT,
# endif
VKD3D_SHADER_TARGET_D3D_ASM,
};
#endif
TRACE("source_type %#x, count %p.\n", source_type, count);
switch (source_type)
{
#ifdef VKD3D_SHADER_UNSUPPORTED_DXIL
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
#endif
case VKD3D_SHADER_SOURCE_DXBC_TPF:
*count = ARRAY_SIZE(dxbc_tpf_types);
return dxbc_tpf_types;
@ -1977,6 +1937,12 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
*count = ARRAY_SIZE(d3dbc_types);
return d3dbc_types;
#ifdef VKD3D_SHADER_UNSUPPORTED_DXIL
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
*count = ARRAY_SIZE(dxbc_dxil_types);
return dxbc_dxil_types;
#endif
default:
*count = 0;
return NULL;
@ -2050,7 +2016,7 @@ void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator,
{
void *params;
if (count > allocator->count - allocator->index)
if (!allocator->current || count > allocator->count - allocator->index)
{
struct vkd3d_shader_param_node *next;

View File

@ -100,6 +100,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
VKD3D_SHADER_WARNING_SPV_INVALID_UAV_FLAGS = 2301,
VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG = 2302,
VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000,
VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001,
@ -148,6 +149,8 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_HLSL_INCONSISTENT_SAMPLER = 5026,
VKD3D_SHADER_ERROR_HLSL_NON_FINITE_RESULT = 5027,
VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028,
VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE = 5029,
VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
@ -199,6 +202,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307,
VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308,
VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309,
VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000,
VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
@ -218,6 +222,8 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015,
VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW = 9016,
VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017,
VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018,
VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019,
VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,
};
@ -445,6 +451,7 @@ enum vkd3d_shader_opcode
VKD3DSIH_NOT,
VKD3DSIH_NRM,
VKD3DSIH_OR,
VKD3DSIH_ORD,
VKD3DSIH_PHASE,
VKD3DSIH_PHI,
VKD3DSIH_POW,
@ -516,10 +523,31 @@ enum vkd3d_shader_opcode
VKD3DSIH_UMAX,
VKD3DSIH_UMIN,
VKD3DSIH_UMUL,
VKD3DSIH_UNO,
VKD3DSIH_USHR,
VKD3DSIH_UTOD,
VKD3DSIH_UTOF,
VKD3DSIH_UTOU,
VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL,
VKD3DSIH_WAVE_ACTIVE_BALLOT,
VKD3DSIH_WAVE_ACTIVE_BIT_AND,
VKD3DSIH_WAVE_ACTIVE_BIT_OR,
VKD3DSIH_WAVE_ACTIVE_BIT_XOR,
VKD3DSIH_WAVE_ALL_BIT_COUNT,
VKD3DSIH_WAVE_ALL_TRUE,
VKD3DSIH_WAVE_ANY_TRUE,
VKD3DSIH_WAVE_IS_FIRST_LANE,
VKD3DSIH_WAVE_OP_ADD,
VKD3DSIH_WAVE_OP_IMAX,
VKD3DSIH_WAVE_OP_IMIN,
VKD3DSIH_WAVE_OP_MAX,
VKD3DSIH_WAVE_OP_MIN,
VKD3DSIH_WAVE_OP_MUL,
VKD3DSIH_WAVE_OP_UMAX,
VKD3DSIH_WAVE_OP_UMIN,
VKD3DSIH_WAVE_PREFIX_BIT_COUNT,
VKD3DSIH_WAVE_READ_LANE_AT,
VKD3DSIH_WAVE_READ_LANE_FIRST,
VKD3DSIH_XOR,
VKD3DSIH_INVALID,
@ -583,6 +611,8 @@ enum vkd3d_shader_register_type
VKD3DSPR_OUTSTENCILREF,
VKD3DSPR_UNDEF,
VKD3DSPR_SSA,
VKD3DSPR_WAVELANECOUNT,
VKD3DSPR_WAVELANEINDEX,
VKD3DSPR_COUNT,
@ -620,14 +650,16 @@ enum vkd3d_data_type
VKD3D_DATA_UINT8,
VKD3D_DATA_UINT64,
VKD3D_DATA_BOOL,
VKD3D_DATA_UINT16,
VKD3D_DATA_HALF,
VKD3D_DATA_COUNT,
};
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT
|| data_type == VKD3D_DATA_UINT64;
return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16
|| data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64;
}
static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
@ -635,6 +667,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
return data_type == VKD3D_DATA_BOOL;
}
static inline bool data_type_is_floating_point(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
}
static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64;
@ -749,11 +786,21 @@ enum vkd3d_shader_uav_flags
VKD3DSUF_ORDER_PRESERVING_COUNTER = 0x100,
};
enum vkd3d_shader_atomic_rmw_flags
{
VKD3DARF_SEQ_CST = 0x1,
VKD3DARF_VOLATILE = 0x2,
};
enum vkd3d_tessellator_domain
{
VKD3D_TESSELLATOR_DOMAIN_INVALID = 0,
VKD3D_TESSELLATOR_DOMAIN_LINE = 1,
VKD3D_TESSELLATOR_DOMAIN_TRIANGLE = 2,
VKD3D_TESSELLATOR_DOMAIN_QUAD = 3,
VKD3D_TESSELLATOR_DOMAIN_COUNT = 4,
};
#define VKD3DSI_NONE 0x0
@ -764,6 +811,7 @@ enum vkd3d_tessellator_domain
#define VKD3DSI_SAMPLE_INFO_UINT 0x1
#define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1
#define VKD3DSI_SHIFT_UNMASKED 0x1
#define VKD3DSI_WAVE_PREFIX 0x1
#define VKD3DSI_PRECISE_X 0x100
#define VKD3DSI_PRECISE_Y 0x200
@ -808,6 +856,8 @@ enum vkd3d_shader_type
VKD3D_SHADER_TYPE_COUNT,
};
struct vkd3d_shader_message_context;
struct vkd3d_shader_version
{
enum vkd3d_shader_type type;
@ -1025,7 +1075,7 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade
unsigned int reg_idx, unsigned int write_mask);
void shader_signature_cleanup(struct shader_signature *signature);
struct vkd3d_shader_desc
struct dxbc_shader_desc
{
const uint32_t *byte_code;
size_t byte_code_size;
@ -1033,11 +1083,6 @@ struct vkd3d_shader_desc
struct shader_signature input_signature;
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
struct
{
uint32_t used, external;
} flat_constant_count[3];
};
struct vkd3d_shader_register_semantic
@ -1079,14 +1124,18 @@ struct vkd3d_shader_tgsm
struct vkd3d_shader_tgsm_raw
{
struct vkd3d_shader_dst_param reg;
unsigned int alignment;
unsigned int byte_count;
bool zero_init;
};
struct vkd3d_shader_tgsm_structured
{
struct vkd3d_shader_dst_param reg;
unsigned int alignment;
unsigned int byte_stride;
unsigned int structure_count;
bool zero_init;
};
struct vkd3d_shader_thread_group_size
@ -1121,6 +1170,8 @@ enum vkd3d_primitive_type
VKD3D_PT_TRIANGLELIST_ADJ = 12,
VKD3D_PT_TRIANGLESTRIP_ADJ = 13,
VKD3D_PT_PATCH = 14,
VKD3D_PT_COUNT = 15,
};
struct vkd3d_shader_primitive_type
@ -1216,6 +1267,12 @@ static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_re
&& (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]);
}
static inline bool register_is_numeric_array(const struct vkd3d_shader_register *reg)
{
return (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP
|| reg->type == VKD3DSPR_GROUPSHAREDMEM);
}
static inline bool vsir_register_is_label(const struct vkd3d_shader_register *reg)
{
return reg->type == VKD3DSPR_LABEL;
@ -1268,6 +1325,8 @@ struct vkd3d_shader_instruction_array
struct vkd3d_shader_immediate_constant_buffer **icbs;
size_t icb_capacity;
size_t icb_count;
struct vkd3d_shader_src_param *outpointid_param;
};
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve);
@ -1278,6 +1337,8 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins
struct vkd3d_shader_immediate_constant_buffer *icb);
bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions,
unsigned int dst, unsigned int src);
struct vkd3d_shader_src_param *instruction_array_create_outpointid_param(
struct vkd3d_shader_instruction_array *instructions);
void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
enum vkd3d_shader_config_flags
@ -1290,7 +1351,12 @@ struct vsir_program
struct vkd3d_shader_version shader_version;
struct vkd3d_shader_instruction_array instructions;
struct shader_signature input_signature;
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
unsigned int input_control_point_count, output_control_point_count;
unsigned int flat_constant_count[3];
unsigned int block_count;
unsigned int temp_count;
unsigned int ssa_count;
@ -1300,8 +1366,15 @@ struct vsir_program
size_t block_name_count;
};
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
void vsir_program_cleanup(struct vsir_program *program);
int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
struct vkd3d_shader_message_context *message_context);
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags,
const char *source_name, struct vkd3d_shader_message_context *message_context);
static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params(
struct vsir_program *program, unsigned int count)
@ -1319,32 +1392,21 @@ struct vkd3d_shader_parser
{
struct vkd3d_shader_message_context *message_context;
struct vkd3d_shader_location location;
struct vsir_program *program;
bool failed;
struct vkd3d_shader_desc shader_desc;
const struct vkd3d_shader_parser_ops *ops;
struct vsir_program program;
uint64_t config_flags;
};
struct vkd3d_shader_parser_ops
{
void (*parser_destroy)(struct vkd3d_shader_parser *parser);
};
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops,
unsigned int instruction_reserve);
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vsir_program *program,
struct vkd3d_shader_message_context *message_context, const char *source_name);
void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser)
static inline enum vkd3d_result vkd3d_shader_parser_validate(struct vkd3d_shader_parser *parser, uint64_t config_flags)
{
parser->ops->parser_destroy(parser);
return vsir_program_validate(parser->program, config_flags,
parser->location.source_name, parser->message_context);
}
struct vkd3d_shader_descriptor_info1
@ -1385,21 +1447,22 @@ struct vkd3d_string_buffer_cache
size_t count, max_count, capacity;
};
enum vsir_asm_dialect
enum vsir_asm_flags
{
VSIR_ASM_VSIR,
VSIR_ASM_D3D,
VSIR_ASM_FLAG_NONE = 0,
VSIR_ASM_FLAG_DUMP_TYPES = 0x1,
};
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
enum vkd3d_result d3d_asm_compile(const struct vsir_program *program,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect);
struct vkd3d_shader_code *out, enum vsir_asm_flags flags);
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer);
struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list);
void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer);
void vkd3d_string_buffer_cache_cleanup(struct vkd3d_string_buffer_cache *list);
void vkd3d_string_buffer_cache_init(struct vkd3d_string_buffer_cache *list);
void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer);
void vkd3d_string_buffer_truncate(struct vkd3d_string_buffer *buffer, size_t size);
int vkd3d_string_buffer_print_f32(struct vkd3d_string_buffer *buffer, float f);
int vkd3d_string_buffer_print_f64(struct vkd3d_string_buffer *buffer, double d);
int vkd3d_string_buffer_printf(struct vkd3d_string_buffer *buffer, const char *format, ...) VKD3D_PRINTF_FUNC(2, 3);
@ -1408,6 +1471,7 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *list, struct
vkd3d_string_buffer_trace_(buffer, __FUNCTION__)
void vkd3d_string_buffer_trace_(const struct vkd3d_string_buffer *buffer, const char *function);
int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args);
void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer);
struct vkd3d_bytecode_buffer
{
@ -1472,35 +1536,32 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s
enum vkd3d_shader_error error, const char *format, va_list args);
void vkd3d_shader_dump_shader(const struct vkd3d_shader_compile_info *compile_info);
uint64_t vkd3d_shader_init_config_flags(void);
void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function);
#define vkd3d_shader_trace_text(text, size) \
vkd3d_shader_trace_text_(text, size, __FUNCTION__)
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);
int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser);
int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser);
int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
void free_shader_desc(struct vkd3d_shader_desc *desc);
void free_dxbc_shader_desc(struct dxbc_shader_desc *desc);
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc);
struct vkd3d_shader_message_context *message_context, const char *source_name, struct dxbc_shader_desc *desc);
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct shader_signature *signature);
struct vkd3d_glsl_generator;
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);
int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator,
struct vsir_program *program, struct vkd3d_shader_code *out);
void vkd3d_glsl_generator_destroy(struct vkd3d_glsl_generator *generator);
int glsl_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
struct vkd3d_shader_message_context *message_context);
#define SPIRV_MAX_SRC_COUNT 6
int spirv_compile(struct vkd3d_shader_parser *parser,
int spirv_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
@ -1513,17 +1574,17 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser);
static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type(
enum vkd3d_data_type data_type)
{
switch (data_type)
{
case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */
case VKD3D_DATA_FLOAT:
case VKD3D_DATA_UNORM:
case VKD3D_DATA_SNORM:
return VKD3D_SHADER_COMPONENT_FLOAT;
case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */
case VKD3D_DATA_UINT:
return VKD3D_SHADER_COMPONENT_UINT;
case VKD3D_DATA_INT:
@ -1585,6 +1646,11 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_resourc
}
}
static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type component_type)
{
return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_UINT64;
}
enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval,
unsigned int index);
@ -1724,6 +1790,31 @@ static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t writ
return compacted_swizzle;
}
static inline uint32_t vsir_swizzle_from_writemask(unsigned int writemask)
{
static const unsigned int swizzles[16] =
{
0,
VKD3D_SHADER_SWIZZLE(X, X, X, X),
VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y),
VKD3D_SHADER_SWIZZLE(X, Y, X, X),
VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z),
VKD3D_SHADER_SWIZZLE(X, Z, X, X),
VKD3D_SHADER_SWIZZLE(Y, Z, X, X),
VKD3D_SHADER_SWIZZLE(X, Y, Z, X),
VKD3D_SHADER_SWIZZLE(W, W, W, W),
VKD3D_SHADER_SWIZZLE(X, W, X, X),
VKD3D_SHADER_SWIZZLE(Y, W, X, X),
VKD3D_SHADER_SWIZZLE(X, Y, W, X),
VKD3D_SHADER_SWIZZLE(Z, W, X, X),
VKD3D_SHADER_SWIZZLE(X, Z, W, X),
VKD3D_SHADER_SWIZZLE(Y, Z, W, X),
VKD3D_SHADER_SWIZZLE(X, Y, Z, W),
};
return swizzles[writemask & 0xf];
}
struct vkd3d_struct
{
enum vkd3d_shader_structure_type type;
@ -1760,7 +1851,4 @@ void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void
void dxbc_writer_init(struct dxbc_writer *dxbc);
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code);
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
const struct vkd3d_shader_compile_info *compile_info);
#endif /* __VKD3D_SHADER_PRIVATE_H */

View File

@ -0,0 +1,254 @@
/*
* Copyright 2024 Stefan Dösinger 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"
struct vkd3d_cache_entry_header
{
uint64_t hash;
uint64_t key_size;
uint64_t value_size;
};
struct vkd3d_shader_cache
{
unsigned int refcount;
struct vkd3d_mutex lock;
struct rb_tree tree;
};
struct shader_cache_entry
{
struct vkd3d_cache_entry_header h;
struct rb_entry entry;
uint8_t *payload;
};
struct shader_cache_key
{
uint64_t hash;
const void *key;
uint64_t key_size;
};
static int vkd3d_shader_cache_compare_key(const void *key, const struct rb_entry *entry)
{
const struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
const struct shader_cache_key *k = key;
int ret;
if ((ret = vkd3d_u64_compare(k->hash, e->h.hash)))
return ret;
if ((ret = vkd3d_u64_compare(k->key_size, e->h.key_size)))
return ret;
/* Until now we have not seen an actual hash collision. If the key didn't match it was always
* due to a bug in the serialization code or memory corruption. If you see this FIXME please
* investigate. */
if ((ret = memcmp(k->key, e->payload, k->key_size)))
FIXME("Actual case of a hash collision found.\n");
return ret;
}
static void vkd3d_shader_cache_add_entry(struct vkd3d_shader_cache *cache,
struct shader_cache_entry *e)
{
rb_put(&cache->tree, &e->h.hash, &e->entry);
}
int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache)
{
struct vkd3d_shader_cache *object;
TRACE("%p.\n", cache);
object = vkd3d_malloc(sizeof(*object));
if (!object)
return VKD3D_ERROR_OUT_OF_MEMORY;
object->refcount = 1;
rb_init(&object->tree, vkd3d_shader_cache_compare_key);
vkd3d_mutex_init(&object->lock);
*cache = object;
return VKD3D_OK;
}
unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache)
{
unsigned int refcount = vkd3d_atomic_increment_u32(&cache->refcount);
TRACE("cache %p refcount %u.\n", cache, refcount);
return refcount;
}
static void vkd3d_shader_cache_destroy_entry(struct rb_entry *entry, void *context)
{
struct shader_cache_entry *e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
vkd3d_free(e->payload);
vkd3d_free(e);
}
unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache)
{
unsigned int refcount = vkd3d_atomic_decrement_u32(&cache->refcount);
TRACE("cache %p refcount %u.\n", cache, refcount);
if (refcount)
return refcount;
rb_destroy(&cache->tree, vkd3d_shader_cache_destroy_entry, NULL);
vkd3d_mutex_destroy(&cache->lock);
vkd3d_free(cache);
return 0;
}
static uint64_t vkd3d_shader_cache_hash_key(const void *key, size_t size)
{
static const uint64_t fnv_prime = 0x00000100000001b3;
uint64_t hash = 0xcbf29ce484222325;
const uint8_t *k = key;
size_t i;
for (i = 0; i < size; ++i)
hash = (hash ^ k[i]) * fnv_prime;
return hash;
}
static void vkd3d_shader_cache_lock(struct vkd3d_shader_cache *cache)
{
vkd3d_mutex_lock(&cache->lock);
}
static void vkd3d_shader_cache_unlock(struct vkd3d_shader_cache *cache)
{
vkd3d_mutex_unlock(&cache->lock);
}
int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,
const void *key, size_t key_size, const void *value, size_t value_size)
{
struct shader_cache_entry *e;
struct shader_cache_key k;
struct rb_entry *entry;
enum vkd3d_result ret;
TRACE("%p, %p, %#zx, %p, %#zx.\n", cache, key, key_size, value, value_size);
k.hash = vkd3d_shader_cache_hash_key(key, key_size);
k.key = key;
k.key_size = key_size;
vkd3d_shader_cache_lock(cache);
entry = rb_get(&cache->tree, &k);
e = entry ? RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry) : NULL;
if (e)
{
WARN("Key already exists, returning VKD3D_ERROR_KEY_ALREADY_EXISTS.\n");
ret = VKD3D_ERROR_KEY_ALREADY_EXISTS;
goto done;
}
e = vkd3d_malloc(sizeof(*e));
if (!e)
{
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto done;
}
e->payload = vkd3d_malloc(key_size + value_size);
if (!e->payload)
{
vkd3d_free(e);
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto done;
}
e->h.key_size = key_size;
e->h.value_size = value_size;
e->h.hash = k.hash;
memcpy(e->payload, key, key_size);
memcpy(e->payload + key_size, value, value_size);
vkd3d_shader_cache_add_entry(cache, e);
TRACE("Cache entry %#"PRIx64" stored.\n", k.hash);
ret = VKD3D_OK;
done:
vkd3d_shader_cache_unlock(cache);
return ret;
}
int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache,
const void *key, size_t key_size, void *value, size_t *value_size)
{
struct shader_cache_entry *e;
struct shader_cache_key k;
struct rb_entry *entry;
enum vkd3d_result ret;
size_t size_in;
TRACE("%p, %p, %#zx, %p, %p.\n", cache, key, key_size, value, value_size);
size_in = *value_size;
k.hash = vkd3d_shader_cache_hash_key(key, key_size);
k.key = key;
k.key_size = key_size;
vkd3d_shader_cache_lock(cache);
entry = rb_get(&cache->tree, &k);
if (!entry)
{
WARN("Entry not found.\n");
ret = VKD3D_ERROR_NOT_FOUND;
goto done;
}
e = RB_ENTRY_VALUE(entry, struct shader_cache_entry, entry);
*value_size = e->h.value_size;
if (!value)
{
TRACE("Found item %#"PRIx64", returning needed size %#"PRIx64".\n",
e->h.hash, e->h.value_size);
ret = VKD3D_OK;
goto done;
}
if (size_in < e->h.value_size)
{
WARN("Output buffer is too small for item %#"PRIx64", got %#zx want %#"PRIx64".\n",
e->h.hash, size_in, e->h.value_size);
ret = VKD3D_ERROR_MORE_DATA;
goto done;
}
memcpy(value, e->payload + e->h.key_size, e->h.value_size);
ret = VKD3D_OK;
TRACE("Returning cached item %#"PRIx64".\n", e->h.hash);
done:
vkd3d_shader_cache_unlock(cache);
return ret;
}

View File

@ -2052,20 +2052,15 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state,
* state when GPU finishes execution of a command list. */
if (is_swapchain_image)
{
if (resource->present_state == D3D12_RESOURCE_STATE_PRESENT)
{
*access_mask = VK_ACCESS_MEMORY_READ_BIT;
*stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
if (image_layout)
*image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
return true;
}
else if (resource->present_state != D3D12_RESOURCE_STATE_COMMON)
{
vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
if (resource->present_state != D3D12_RESOURCE_STATE_PRESENT)
return vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0,
resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout);
return true;
}
*access_mask = VK_ACCESS_MEMORY_READ_BIT;
*stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
if (image_layout)
*image_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
return true;
}
*access_mask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
@ -5414,6 +5409,26 @@ static const struct vkd3d_format *vkd3d_fixup_clear_uav_uint_colour(struct d3d12
| ((colour->uint32[2] & 0x3ff) << 22);
return vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false);
case DXGI_FORMAT_B5G6R5_UNORM:
colour->uint32[0] = (colour->uint32[2] & 0x1f)
| ((colour->uint32[1] & 0x3f) << 5)
| ((colour->uint32[0] & 0x1f) << 11);
return vkd3d_get_format(device, DXGI_FORMAT_R16_UINT, false);
case DXGI_FORMAT_B5G5R5A1_UNORM:
colour->uint32[0] = (colour->uint32[2] & 0x1f)
| ((colour->uint32[1] & 0x1f) << 5)
| ((colour->uint32[0] & 0x1f) << 10)
| ((colour->uint32[3] & 0x1) << 15);
return vkd3d_get_format(device, DXGI_FORMAT_R16_UINT, false);
case DXGI_FORMAT_B4G4R4A4_UNORM:
colour->uint32[0] = (colour->uint32[2] & 0xf)
| ((colour->uint32[1] & 0xf) << 4)
| ((colour->uint32[0] & 0xf) << 8)
| ((colour->uint32[3] & 0xf) << 12);
return vkd3d_get_format(device, DXGI_FORMAT_R16_UINT, false);
default:
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -1271,7 +1271,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource2 *
|| IsEqualGUID(riid, &IID_ID3D12Object)
|| IsEqualGUID(riid, &IID_IUnknown))
{
ID3D12Resource_AddRef(iface);
ID3D12Resource2_AddRef(iface);
*object = iface;
return S_OK;
}
@ -1857,6 +1857,7 @@ static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC1
HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC1 *desc, struct d3d12_device *device)
{
const D3D12_MIP_REGION *mip_region = &desc->SamplerFeedbackMipRegion;
const struct vkd3d_format *format;
switch (desc->Dimension)
@ -1892,6 +1893,13 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC1 *desc, struct d3
WARN("Invalid sample count 0.\n");
return E_INVALIDARG;
}
if (desc->SampleDesc.Count > 1
&& !(desc->Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)))
{
WARN("Sample count %u invalid without ALLOW_RENDER_TARGET or ALLOW_DEPTH_STENCIL.\n",
desc->SampleDesc.Count);
return E_INVALIDARG;
}
if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
{
@ -1926,6 +1934,12 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC1 *desc, struct d3
d3d12_validate_resource_flags(desc->Flags);
if (mip_region->Width && mip_region->Height && mip_region->Depth)
{
FIXME("Unhandled sampler feedback mip region size (%u, %u, %u).\n", mip_region->Width, mip_region->Height,
mip_region->Depth);
}
return S_OK;
}
@ -1989,6 +2003,11 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
WARN("Invalid initial resource state %#x.\n", initial_state);
return E_INVALIDARG;
}
if (initial_state == D3D12_RESOURCE_STATE_RENDER_TARGET && !(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET))
{
WARN("Invalid initial resource state %#x for non-render-target.\n", initial_state);
return E_INVALIDARG;
}
if (optimized_clear_value && d3d12_resource_is_buffer(resource))
{
@ -2253,7 +2272,7 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
HRESULT vkd3d_create_image_resource(ID3D12Device *device,
const struct vkd3d_image_resource_create_info *create_info, ID3D12Resource **resource)
{
struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device7((ID3D12Device7 *)device);
struct d3d12_device *d3d12_device = unsafe_impl_from_ID3D12Device9((ID3D12Device9 *)device);
struct d3d12_resource *object;
HRESULT hr;
@ -2331,16 +2350,16 @@ static void *vkd3d_desc_object_cache_get(struct vkd3d_desc_object_cache *cache)
i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK;
for (;;)
{
if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1))
if (vkd3d_atomic_compare_exchange_u32(&cache->heads[i].spinlock, 0, 1))
{
if ((u.object = cache->heads[i].head))
{
vkd3d_atomic_decrement_u32(&cache->free_count);
cache->heads[i].head = u.header->next;
vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
return u.object;
}
vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
}
/* Keeping a free count avoids uncertainty over when this loop should terminate,
* which could result in excess allocations gradually increasing without limit. */
@ -2362,7 +2381,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache,
i = vkd3d_atomic_increment_u32(&cache->next_index) & HEAD_INDEX_MASK;
for (;;)
{
if (vkd3d_atomic_compare_exchange(&cache->heads[i].spinlock, 0, 1))
if (vkd3d_atomic_compare_exchange_u32(&cache->heads[i].spinlock, 0, 1))
break;
i = (i + 1) & HEAD_INDEX_MASK;
}
@ -2370,7 +2389,7 @@ static void vkd3d_desc_object_cache_push(struct vkd3d_desc_object_cache *cache,
head = cache->heads[i].head;
u.header->next = head;
cache->heads[i].head = u.object;
vkd3d_atomic_exchange(&cache->heads[i].spinlock, 0);
vkd3d_atomic_exchange_u32(&cache->heads[i].spinlock, 0);
vkd3d_atomic_increment_u32(&cache->free_count);
}
@ -2454,7 +2473,7 @@ void vkd3d_view_decref(void *view, struct d3d12_device *device)
static inline void d3d12_desc_replace(struct d3d12_desc *dst, void *view, struct d3d12_device *device)
{
if ((view = vkd3d_atomic_exchange_pointer(&dst->s.u.object, view)))
if ((view = vkd3d_atomic_exchange_ptr(&dst->s.u.object, view)))
vkd3d_view_decref(view, device);
}
@ -2633,7 +2652,7 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr
union d3d12_desc_object u;
unsigned int i, next;
if ((i = vkd3d_atomic_exchange(&descriptor_heap->dirty_list_head, UINT_MAX)) == UINT_MAX)
if ((i = vkd3d_atomic_exchange_u32(&descriptor_heap->dirty_list_head, UINT_MAX)) == UINT_MAX)
return;
writes.null_vk_cbv_info.buffer = VK_NULL_HANDLE;
@ -2648,7 +2667,7 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr
for (; i != UINT_MAX; i = next)
{
src = &descriptors[i];
next = vkd3d_atomic_exchange(&src->next, 0);
next = vkd3d_atomic_exchange_u32(&src->next, 0);
next = (int)next >> 1;
/* A race exists here between updating src->next and getting the current object. The best
@ -2676,13 +2695,13 @@ static void d3d12_desc_mark_as_modified(struct d3d12_desc *dst, struct d3d12_des
head = descriptor_heap->dirty_list_head;
/* Only one thread can swap the value away from zero. */
if (!vkd3d_atomic_compare_exchange(&dst->next, 0, (head << 1) | 1))
if (!vkd3d_atomic_compare_exchange_u32(&dst->next, 0, (head << 1) | 1))
return;
/* Now it is safe to modify 'next' to another nonzero value if necessary. */
while (!vkd3d_atomic_compare_exchange(&descriptor_heap->dirty_list_head, head, i))
while (!vkd3d_atomic_compare_exchange_u32(&descriptor_heap->dirty_list_head, head, i))
{
head = descriptor_heap->dirty_list_head;
vkd3d_atomic_exchange(&dst->next, (head << 1) | 1);
vkd3d_atomic_exchange_u32(&dst->next, (head << 1) | 1);
}
}
@ -4265,12 +4284,14 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript
VkDescriptorSetVariableDescriptorCountAllocateInfoEXT set_size;
VkDescriptorSetAllocateInfo set_desc;
VkResult vr;
HRESULT hr;
if (!device->vk_descriptor_heap_layouts[set].vk_set_layout)
{
/* Set 0 uses mutable descriptors, and this set is unused. */
if (!descriptor_heap->vk_descriptor_sets[0].vk_set)
d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0);
if (!descriptor_heap->vk_descriptor_sets[0].vk_set
&& FAILED(hr = d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0)))
return hr;
descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set;
descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type;
return S_OK;

View File

@ -2045,6 +2045,9 @@ static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState
d3d12_pipeline_uav_counter_state_cleanup(&state->uav_counters, device);
if (state->implicit_root_signature)
d3d12_root_signature_Release(state->implicit_root_signature);
vkd3d_free(state);
d3d12_device_release(device);
@ -2156,6 +2159,8 @@ static unsigned int feature_flags_compile_option(const struct d3d12_device *devi
flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64;
if (device->feature_options.DoublePrecisionFloatShaderOps)
flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLOAT64;
if (device->feature_options1.WaveOps)
flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_WAVE_OPS;
return flags;
}
@ -2173,7 +2178,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device,
const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_11},
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_12},
{VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)},
{VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0},
{VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)},
@ -2228,7 +2233,7 @@ static int vkd3d_scan_dxbc(const struct d3d12_device *device, const D3D12_SHADER
const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_11},
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_12},
{VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)},
};
@ -2413,8 +2418,8 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_shader_interface_info shader_interface;
struct vkd3d_shader_descriptor_offset_info offset_info;
const struct d3d12_root_signature *root_signature;
struct vkd3d_shader_spirv_target_info target_info;
struct d3d12_root_signature *root_signature;
VkPipelineLayout vk_pipeline_layout;
HRESULT hr;
@ -2425,17 +2430,31 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
if (!(root_signature = unsafe_impl_from_ID3D12RootSignature(desc->root_signature)))
{
WARN("Root signature is NULL.\n");
return E_INVALIDARG;
TRACE("Root signature is NULL, looking for an embedded signature.\n");
if (FAILED(hr = d3d12_root_signature_create(device,
desc->cs.pShaderBytecode, desc->cs.BytecodeLength, &root_signature)))
{
WARN("Failed to find an embedded root signature, hr %s.\n", debugstr_hresult(hr));
return hr;
}
state->implicit_root_signature = &root_signature->ID3D12RootSignature_iface;
}
else
{
state->implicit_root_signature = NULL;
}
if (FAILED(hr = d3d12_pipeline_state_find_and_init_uav_counters(state, device, root_signature,
&desc->cs, VK_SHADER_STAGE_COMPUTE_BIT)))
{
if (state->implicit_root_signature)
d3d12_root_signature_Release(state->implicit_root_signature);
return hr;
}
memset(&target_info, 0, sizeof(target_info));
target_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO;
target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
target_info.environment = device->environment;
target_info.extensions = device->vk_info.shader_extensions;
target_info.extension_count = device->vk_info.shader_extension_count;
@ -2476,6 +2495,8 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
{
WARN("Failed to create Vulkan compute pipeline, hr %s.\n", debugstr_hresult(hr));
d3d12_pipeline_uav_counter_state_cleanup(&state->uav_counters, device);
if (state->implicit_root_signature)
d3d12_root_signature_Release(state->implicit_root_signature);
return hr;
}
@ -2483,6 +2504,8 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
{
VK_CALL(vkDestroyPipeline(device->vk_device, state->u.compute.vk_pipeline, NULL));
d3d12_pipeline_uav_counter_state_cleanup(&state->uav_counters, device);
if (state->implicit_root_signature)
d3d12_root_signature_Release(state->implicit_root_signature);
return hr;
}
@ -3156,7 +3179,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
ps_target_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO;
ps_target_info.next = NULL;
ps_target_info.entry_point = "main";
ps_target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
ps_target_info.environment = device->environment;
ps_target_info.extensions = vk_info->shader_extensions;
ps_target_info.extension_count = vk_info->shader_extension_count;
ps_target_info.parameters = ps_shader_parameters;
@ -3186,7 +3209,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
memset(&target_info, 0, sizeof(target_info));
target_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO;
target_info.environment = VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
target_info.environment = device->environment;
target_info.extensions = vk_info->shader_extensions;
target_info.extension_count = vk_info->shader_extension_count;
@ -3484,6 +3507,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
goto fail;
state->vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
state->implicit_root_signature = NULL;
d3d12_device_add_ref(state->device = device);
return S_OK;
@ -3887,7 +3911,7 @@ static int compile_hlsl_cs(const struct vkd3d_shader_code *hlsl, struct vkd3d_sh
static const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_11},
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_12},
};
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;

View File

@ -87,6 +87,8 @@ static const struct vkd3d_format vkd3d_formats[] =
{DXGI_FORMAT_R8_SNORM, VK_FORMAT_R8_SNORM, 1, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_R8_SINT, VK_FORMAT_R8_SINT, 1, 1, 1, 1, COLOR, 1, SINT},
{DXGI_FORMAT_A8_UNORM, VK_FORMAT_R8_UNORM, 1, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_B5G6R5_UNORM, VK_FORMAT_R5G6B5_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_B5G5R5A1_UNORM, VK_FORMAT_A1R5G5B5_UNORM_PACK16, 2, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_B8G8R8X8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1},
{DXGI_FORMAT_B8G8R8A8_TYPELESS, VK_FORMAT_B8G8R8A8_UNORM, 4, 1, 1, 1, COLOR, 1, TYPELESS},
@ -116,6 +118,9 @@ static const struct vkd3d_format vkd3d_formats[] =
{DXGI_FORMAT_BC7_UNORM_SRGB, VK_FORMAT_BC7_SRGB_BLOCK, 1, 4, 4, 16, COLOR, 1},
};
static const struct vkd3d_format format_b4g4r4a4 =
{DXGI_FORMAT_B4G4R4A4_UNORM, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, 2, 1, 1, 1, COLOR, 1};
/* Each depth/stencil format is only compatible with itself in Vulkan. */
static const struct vkd3d_format vkd3d_depth_stencil_formats[] =
{
@ -449,6 +454,11 @@ const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
return &vkd3d_formats[i];
}
/* Do not check VkPhysicalDevice4444FormatsFeaturesEXT because apps
* should query format support, which returns more detailed info. */
if (dxgi_format == format_b4g4r4a4.dxgi_format && device->vk_info.EXT_4444_formats)
return &format_b4g4r4a4;
return NULL;
}
@ -891,6 +901,30 @@ bool vkd3d_get_program_name(char program_name[PATH_MAX])
return true;
}
#elif defined(WIN32)
bool vkd3d_get_program_name(char program_name[PATH_MAX])
{
char buffer[MAX_PATH];
char *p, *name;
size_t len;
*program_name = '\0';
len = GetModuleFileNameA(NULL, buffer, ARRAY_SIZE(buffer));
if (!(len && len < MAX_PATH))
return false;
name = buffer;
if ((p = strrchr(name, '/')))
name = p + 1;
if ((p = strrchr(name, '\\')))
name = p + 1;
len = strlen(name) + 1;
memcpy(program_name, name, len);
return true;
}
#else
bool vkd3d_get_program_name(char program_name[PATH_MAX])

View File

@ -71,11 +71,11 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info,
if (!device)
{
ID3D12Device_Release(&object->ID3D12Device7_iface);
ID3D12Device9_Release(&object->ID3D12Device9_iface);
return S_FALSE;
}
return return_interface(&object->ID3D12Device7_iface, &IID_ID3D12Device, iid, device);
return return_interface(&object->ID3D12Device9_iface, &IID_ID3D12Device, iid, device);
}
/* ID3D12RootSignatureDeserializer */
@ -453,11 +453,10 @@ HRESULT vkd3d_serialize_root_signature(const D3D12_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 %s.\n", debugstr_hresult(hr));
}
if (!error_blob)
vkd3d_shader_free_messages(messages);
else if (messages && FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob)))
ERR("Failed to create error blob, hr %s.\n", debugstr_hresult(hr));
return hresult_from_vkd3d_result(ret);
}
vkd3d_shader_free_messages(messages);
@ -494,11 +493,10 @@ HRESULT vkd3d_serialize_versioned_root_signature(const D3D12_VERSIONED_ROOT_SIGN
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 %s.\n", debugstr_hresult(hr));
}
if (!error_blob)
vkd3d_shader_free_messages(messages);
else if (messages && FAILED(hr = vkd3d_blob_create(messages, strlen(messages), error_blob)))
ERR("Failed to create error blob, hr %s.\n", debugstr_hresult(hr));
return hresult_from_vkd3d_result(ret);
}
vkd3d_shader_free_messages(messages);

View File

@ -19,15 +19,14 @@
#ifndef __VKD3D_PRIVATE_H
#define __VKD3D_PRIVATE_H
#ifndef __MINGW32__
#define WIDL_C_INLINE_WRAPPERS
#endif
#define COBJMACROS
#define NONAMELESSUNION
#define VK_NO_PROTOTYPES
#define CONST_VTABLE
#ifdef _WIN32
# define _WIN32_WINNT 0x0600 /* for condition variables */
#endif
#include "vkd3d_common.h"
#include "vkd3d_blob.h"
#include "vkd3d_memory.h"
@ -55,7 +54,7 @@
#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
#define VKD3D_MAX_SHADER_EXTENSIONS 4u
#define VKD3D_MAX_SHADER_EXTENSIONS 5u
#define VKD3D_MAX_SHADER_STAGES 5u
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
#define VKD3D_MAX_DEVICE_BLOCKED_QUEUES 16u
@ -128,11 +127,13 @@ struct vkd3d_vulkan_info
bool KHR_sampler_mirror_clamp_to_edge;
bool KHR_timeline_semaphore;
/* EXT device extensions */
bool EXT_4444_formats;
bool EXT_calibrated_timestamps;
bool EXT_conditional_rendering;
bool EXT_debug_marker;
bool EXT_depth_clip_enable;
bool EXT_descriptor_indexing;
bool EXT_fragment_shader_interlock;
bool EXT_mutable_descriptor_type;
bool EXT_robustness2;
bool EXT_shader_demote_to_helper_invocation;
@ -184,6 +185,7 @@ struct vkd3d_instance
struct vkd3d_vulkan_info vk_info;
struct vkd3d_vk_global_procs vk_global_procs;
void *libvulkan;
uint32_t vk_api_version;
uint64_t config_flags;
enum vkd3d_api_version api_version;
@ -195,240 +197,14 @@ struct vkd3d_instance
unsigned int refcount;
};
#ifdef _WIN32
union vkd3d_thread_handle
{
void *handle;
};
struct vkd3d_mutex
{
CRITICAL_SECTION lock;
};
struct vkd3d_cond
{
CONDITION_VARIABLE cond;
};
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
{
InitializeCriticalSection(&lock->lock);
}
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
{
EnterCriticalSection(&lock->lock);
}
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
{
LeaveCriticalSection(&lock->lock);
}
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
{
DeleteCriticalSection(&lock->lock);
}
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
{
InitializeConditionVariable(&cond->cond);
}
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
{
WakeConditionVariable(&cond->cond);
}
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
{
WakeAllConditionVariable(&cond->cond);
}
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
{
if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))
ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError());
}
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
{
}
static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg)
{
return InterlockedCompareExchange((LONG volatile *)x, xchg, cmp) == cmp;
}
static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
{
return InterlockedExchange((LONG volatile *)x, val);
}
static inline bool vkd3d_atomic_compare_exchange_pointer(void * volatile *x, void *cmp, void *xchg)
{
return InterlockedCompareExchangePointer(x, xchg, cmp) == cmp;
}
static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
{
return InterlockedExchangePointer(x, val);
}
#else /* _WIN32 */
#include <pthread.h>
union vkd3d_thread_handle
{
#ifndef _WIN32
pthread_t pthread;
#endif
void *handle;
};
struct vkd3d_mutex
{
pthread_mutex_t lock;
};
struct vkd3d_cond
{
pthread_cond_t cond;
};
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
{
int ret;
ret = pthread_mutex_init(&lock->lock, NULL);
if (ret)
ERR("Could not initialize the mutex, error %d.\n", ret);
}
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
{
int ret;
ret = pthread_mutex_lock(&lock->lock);
if (ret)
ERR("Could not lock the mutex, error %d.\n", ret);
}
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
{
int ret;
ret = pthread_mutex_unlock(&lock->lock);
if (ret)
ERR("Could not unlock the mutex, error %d.\n", ret);
}
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
{
int ret;
ret = pthread_mutex_destroy(&lock->lock);
if (ret)
ERR("Could not destroy the mutex, error %d.\n", ret);
}
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
{
int ret;
ret = pthread_cond_init(&cond->cond, NULL);
if (ret)
ERR("Could not initialize the condition variable, error %d.\n", ret);
}
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
{
int ret;
ret = pthread_cond_signal(&cond->cond);
if (ret)
ERR("Could not signal the condition variable, error %d.\n", ret);
}
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
{
int ret;
ret = pthread_cond_broadcast(&cond->cond);
if (ret)
ERR("Could not broadcast the condition variable, error %d.\n", ret);
}
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
{
int ret;
ret = pthread_cond_wait(&cond->cond, &lock->lock);
if (ret)
ERR("Could not wait on the condition variable, error %d.\n", ret);
}
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
{
int ret;
ret = pthread_cond_destroy(&cond->cond);
if (ret)
ERR("Could not destroy the condition variable, error %d.\n", ret);
}
# if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg)
{
return __sync_bool_compare_and_swap(x, cmp, xchg);
}
static inline bool vkd3d_atomic_compare_exchange_pointer(void * volatile *x, void *cmp, void *xchg)
{
return __sync_bool_compare_and_swap(x, cmp, xchg);
}
# else
# error "vkd3d_atomic_compare_exchange() not implemented for this platform"
# endif
# if HAVE_ATOMIC_EXCHANGE_N
static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
{
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
}
static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
{
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
}
# elif HAVE_SYNC_BOOL_COMPARE_AND_SWAP
static inline unsigned int vkd3d_atomic_exchange(unsigned int volatile *x, unsigned int val)
{
unsigned int i;
do
{
i = *x;
} while (!__sync_bool_compare_and_swap(x, i, val));
return i;
}
static inline void *vkd3d_atomic_exchange_pointer(void * volatile *x, void *val)
{
void *p;
do
{
p = *x;
} while (!__sync_bool_compare_and_swap(x, p, val));
return p;
}
# else
# error "vkd3d_atomic_exchange() not implemented for this platform"
# endif
#endif /* _WIN32 */
HRESULT vkd3d_create_thread(struct vkd3d_instance *instance,
PFN_vkd3d_thread thread_main, void *data, union vkd3d_thread_handle *thread);
HRESULT vkd3d_join_thread(struct vkd3d_instance *instance, union vkd3d_thread_handle *thread);
@ -890,7 +666,7 @@ static inline bool vkd3d_view_incref(void *desc)
if (refcount <= 0)
return false;
}
while (!vkd3d_atomic_compare_exchange(&h->refcount, refcount, refcount + 1));
while (!vkd3d_atomic_compare_exchange_u32(&h->refcount, refcount, refcount + 1));
return true;
}
@ -1279,6 +1055,7 @@ struct d3d12_pipeline_state
struct d3d12_pipeline_uav_counter_state uav_counters;
ID3D12RootSignature *implicit_root_signature;
struct d3d12_device *device;
struct vkd3d_private_store private_store;
@ -1735,7 +1512,7 @@ struct vkd3d_desc_object_cache
/* ID3D12Device */
struct d3d12_device
{
ID3D12Device7 ID3D12Device7_iface;
ID3D12Device9 ID3D12Device9_iface;
unsigned int refcount;
VkDevice vk_device;
@ -1743,6 +1520,7 @@ struct d3d12_device
struct vkd3d_vk_device_procs vk_procs;
PFN_vkd3d_signal_event signal_event;
size_t wchar_size;
enum vkd3d_shader_spirv_environment environment;
struct vkd3d_gpu_va_allocator gpu_va_allocator;
@ -1810,29 +1588,29 @@ struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device, D3
bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent);
void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
const char *message, ...) VKD3D_PRINTF_FUNC(3, 4);
struct d3d12_device *unsafe_impl_from_ID3D12Device7(ID3D12Device7 *iface);
struct d3d12_device *unsafe_impl_from_ID3D12Device9(ID3D12Device9 *iface);
HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap);
void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap);
static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object)
{
return ID3D12Device7_QueryInterface(&device->ID3D12Device7_iface, iid, object);
return ID3D12Device9_QueryInterface(&device->ID3D12Device9_iface, iid, object);
}
static inline ULONG d3d12_device_add_ref(struct d3d12_device *device)
{
return ID3D12Device7_AddRef(&device->ID3D12Device7_iface);
return ID3D12Device9_AddRef(&device->ID3D12Device9_iface);
}
static inline ULONG d3d12_device_release(struct d3d12_device *device)
{
return ID3D12Device7_Release(&device->ID3D12Device7_iface);
return ID3D12Device9_Release(&device->ID3D12Device9_iface);
}
static inline unsigned int d3d12_device_get_descriptor_handle_increment_size(struct d3d12_device *device,
D3D12_DESCRIPTOR_HEAP_TYPE descriptor_type)
{
return ID3D12Device7_GetDescriptorHandleIncrementSize(&device->ID3D12Device7_iface, descriptor_type);
return ID3D12Device9_GetDescriptorHandleIncrementSize(&device->ID3D12Device9_iface, descriptor_type);
}
/* utils */
@ -1993,4 +1771,14 @@ static inline void vkd3d_prepend_struct(void *header, void *structure)
vkd3d_header->next = vkd3d_structure;
}
struct vkd3d_shader_cache;
int vkd3d_shader_open_cache(struct vkd3d_shader_cache **cache);
unsigned int vkd3d_shader_cache_incref(struct vkd3d_shader_cache *cache);
unsigned int vkd3d_shader_cache_decref(struct vkd3d_shader_cache *cache);
int vkd3d_shader_cache_put(struct vkd3d_shader_cache *cache,
const void *key, size_t key_size, const void *value, size_t value_size);
int vkd3d_shader_cache_get(struct vkd3d_shader_cache *cache,
const void *key, size_t key_size, void *value, size_t *value_size);
#endif /* __VKD3D_PRIVATE_H */