2022-01-26 17:40:28 -08:00
|
|
|
/*
|
|
|
|
* Copyright 2016-2018 Józef Kucia for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __VKD3D_TEST_UTILS_H
|
|
|
|
#define __VKD3D_TEST_UTILS_H
|
|
|
|
|
2024-07-10 03:30:10 -07:00
|
|
|
/* Hack for MinGW-w64 headers.
|
|
|
|
*
|
|
|
|
* We want to use WIDL C inline wrappers because some methods
|
|
|
|
* in D3D12 interfaces return aggregate objects. Unfortunately,
|
|
|
|
* WIDL C inline wrappers are broken when used with MinGW-w64
|
|
|
|
* headers because FORCEINLINE expands to extern inline
|
|
|
|
* which leads to the "multiple storage classes in declaration
|
|
|
|
* specifiers" compiler error.
|
|
|
|
*/
|
|
|
|
#ifdef __MINGW32__
|
|
|
|
# include <_mingw.h>
|
|
|
|
# ifdef __MINGW64_VERSION_MAJOR
|
|
|
|
# undef __forceinline
|
|
|
|
# define __forceinline __inline__ __attribute__((__always_inline__,__gnu_inline__))
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
#define WIDL_C_INLINE_WRAPPERS
|
2022-01-26 17:40:33 -08:00
|
|
|
#include <limits.h>
|
2022-01-26 17:40:28 -08:00
|
|
|
#include <stdbool.h>
|
2022-05-17 06:45:38 -07:00
|
|
|
#include <stdint.h>
|
2022-01-26 17:40:28 -08:00
|
|
|
#include <stdlib.h>
|
2022-05-17 06:45:40 -07:00
|
|
|
#include "vkd3d_test.h"
|
2024-03-31 13:54:14 -07:00
|
|
|
#include "vkd3d_d3d12.h"
|
2024-07-03 19:14:52 -07:00
|
|
|
#include "vkd3d_d3dcompiler.h"
|
|
|
|
#include "vkd3d_shader.h"
|
|
|
|
#include "dxcompiler.h"
|
2022-01-26 17:40:28 -08:00
|
|
|
|
2022-01-26 17:40:33 -08:00
|
|
|
struct vec2
|
|
|
|
{
|
|
|
|
float x, y;
|
|
|
|
};
|
|
|
|
|
2022-01-26 17:40:28 -08:00
|
|
|
struct vec4
|
|
|
|
{
|
|
|
|
float x, y, z, w;
|
|
|
|
};
|
|
|
|
|
2023-11-09 20:48:23 -08:00
|
|
|
struct dvec2
|
|
|
|
{
|
|
|
|
double x, y;
|
|
|
|
};
|
|
|
|
|
2023-03-17 04:35:13 -07:00
|
|
|
struct ivec4
|
|
|
|
{
|
|
|
|
int x, y, z, w;
|
|
|
|
};
|
|
|
|
|
2021-08-16 16:55:56 -07:00
|
|
|
struct uvec4
|
|
|
|
{
|
|
|
|
unsigned int x, y, z, w;
|
|
|
|
};
|
|
|
|
|
2023-11-09 20:48:23 -08:00
|
|
|
struct i64vec2
|
|
|
|
{
|
|
|
|
int64_t x, y;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct u64vec2
|
|
|
|
{
|
|
|
|
uint64_t x, y;
|
|
|
|
};
|
|
|
|
|
2022-05-17 06:45:38 -07:00
|
|
|
struct resource_readback
|
|
|
|
{
|
|
|
|
uint64_t width;
|
|
|
|
unsigned int height;
|
|
|
|
unsigned int depth;
|
|
|
|
uint64_t row_pitch;
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
2022-01-26 17:40:28 -08:00
|
|
|
static inline bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
|
|
|
|
{
|
|
|
|
size_t new_capacity, max_capacity;
|
|
|
|
void *new_elements;
|
|
|
|
|
|
|
|
if (element_count <= *capacity)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
max_capacity = ~(size_t)0 / element_size;
|
|
|
|
if (max_capacity < element_count)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
new_capacity = max(*capacity, 4);
|
|
|
|
while (new_capacity < element_count && new_capacity <= max_capacity / 2)
|
|
|
|
new_capacity *= 2;
|
|
|
|
|
|
|
|
if (new_capacity < element_count)
|
|
|
|
new_capacity = element_count;
|
|
|
|
|
|
|
|
if (!(new_elements = realloc(*elements, new_capacity * element_size)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*elements = new_elements;
|
|
|
|
*capacity = new_capacity;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-06-23 13:36:26 -07:00
|
|
|
static bool compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
unsigned int diff = x > y ? x - y : y - x;
|
|
|
|
|
|
|
|
return diff <= max_diff;
|
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
static bool compare_uint64(uint64_t x, uint64_t y, uint64_t max_diff)
|
|
|
|
{
|
|
|
|
uint64_t diff = x > y ? x - y : y - x;
|
|
|
|
|
|
|
|
return diff <= max_diff;
|
|
|
|
}
|
|
|
|
|
2023-10-13 14:27:44 -07:00
|
|
|
static bool compare_color(DWORD c1, DWORD c2, BYTE max_diff)
|
|
|
|
{
|
|
|
|
return compare_uint(c1 & 0xff, c2 & 0xff, max_diff)
|
|
|
|
&& compare_uint((c1 >> 8) & 0xff, (c2 >> 8) & 0xff, max_diff)
|
|
|
|
&& compare_uint((c1 >> 16) & 0xff, (c2 >> 16) & 0xff, max_diff)
|
|
|
|
&& compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff);
|
|
|
|
}
|
|
|
|
|
2022-01-26 17:40:33 -08:00
|
|
|
static bool compare_float(float f, float g, unsigned int ulps)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
float f;
|
|
|
|
int i;
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.f = f;
|
|
|
|
x = u.i;
|
|
|
|
u.f = g;
|
|
|
|
y = u.i;
|
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
x = INT_MIN - x;
|
|
|
|
if (y < 0)
|
|
|
|
y = INT_MIN - y;
|
|
|
|
|
2023-06-23 13:36:26 -07:00
|
|
|
return compare_uint(x, y, ulps);
|
2022-01-26 17:40:33 -08:00
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
static bool compare_double(double f, double g, unsigned int ulps)
|
|
|
|
{
|
|
|
|
int64_t x, y;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
double f;
|
|
|
|
int64_t i;
|
|
|
|
} u;
|
|
|
|
|
|
|
|
u.f = f;
|
|
|
|
x = u.i;
|
|
|
|
u.f = g;
|
|
|
|
y = u.i;
|
|
|
|
|
|
|
|
if (x < 0)
|
|
|
|
x = INT64_MIN - x;
|
|
|
|
if (y < 0)
|
|
|
|
y = INT64_MIN - y;
|
|
|
|
|
|
|
|
return compare_uint64(x, y, ulps);
|
|
|
|
}
|
|
|
|
|
2021-08-16 16:55:56 -07:00
|
|
|
static inline bool compare_uvec4(const struct uvec4 *v1, const struct uvec4 *v2)
|
|
|
|
{
|
|
|
|
return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w;
|
|
|
|
}
|
|
|
|
|
2022-01-26 17:40:33 -08:00
|
|
|
static inline bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps)
|
|
|
|
{
|
|
|
|
return compare_float(v1->x, v2->x, ulps)
|
|
|
|
&& compare_float(v1->y, v2->y, ulps)
|
|
|
|
&& compare_float(v1->z, v2->z, ulps)
|
|
|
|
&& compare_float(v1->w, v2->w, ulps);
|
|
|
|
}
|
|
|
|
|
2022-04-17 23:33:58 -07:00
|
|
|
static inline void set_rect(RECT *rect, int left, int top, int right, int bottom)
|
|
|
|
{
|
|
|
|
rect->left = left;
|
|
|
|
rect->right = right;
|
|
|
|
rect->top = top;
|
|
|
|
rect->bottom = bottom;
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:40 -07:00
|
|
|
static void *get_readback_data(const struct resource_readback *rb,
|
|
|
|
unsigned int x, unsigned int y, unsigned int z, size_t element_size)
|
|
|
|
{
|
|
|
|
unsigned int slice_pitch = rb->row_pitch * rb->height;
|
|
|
|
return &((uint8_t *)rb->data)[slice_pitch * z + rb->row_pitch * y + x * element_size];
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:42 -07:00
|
|
|
static float get_readback_float(const struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
|
|
{
|
|
|
|
return *(float *)get_readback_data(rb, x, y, 0, sizeof(float));
|
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
static double get_readback_double(const struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
|
|
{
|
|
|
|
return *(double *)get_readback_data(rb, x, y, 0, sizeof(double));
|
|
|
|
}
|
|
|
|
|
2023-10-13 14:27:44 -07:00
|
|
|
static unsigned int get_readback_uint(const struct resource_readback *rb, unsigned int x, unsigned int y, unsigned int z)
|
|
|
|
{
|
|
|
|
return *(unsigned int*)get_readback_data(rb, x, y, z, sizeof(unsigned int));
|
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
static uint64_t get_readback_uint64(const struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
|
|
{
|
|
|
|
return *(uint64_t*)get_readback_data(rb, x, y, 0, sizeof(uint64_t));
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:40 -07:00
|
|
|
static const struct vec4 *get_readback_vec4(const struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
|
|
{
|
|
|
|
return get_readback_data(rb, x, y, 0, sizeof(struct vec4));
|
|
|
|
}
|
|
|
|
|
2023-10-13 14:27:44 -07:00
|
|
|
static const struct uvec4 *get_readback_uvec4(const struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
|
|
{
|
|
|
|
return get_readback_data(rb, x, y, 0, sizeof(struct uvec4));
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:42 -07:00
|
|
|
#define check_readback_data_float(a, b, c, d) check_readback_data_float_(__LINE__, a, b, c, d)
|
|
|
|
static inline void check_readback_data_float_(unsigned int line, const struct resource_readback *rb,
|
|
|
|
const RECT *rect, float expected, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
RECT r = {0, 0, rb->width, rb->height};
|
|
|
|
unsigned int x = 0, y;
|
|
|
|
bool all_match = true;
|
|
|
|
float got = 0;
|
|
|
|
|
|
|
|
if (rect)
|
|
|
|
r = *rect;
|
|
|
|
|
|
|
|
for (y = r.top; y < r.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = r.left; x < r.right; ++x)
|
|
|
|
{
|
|
|
|
got = get_readback_float(rb, x, y);
|
|
|
|
if (!compare_float(got, expected, max_diff))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got %.8e, expected %.8e at (%u, %u).\n", got, expected, x, y);
|
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
#define check_readback_data_double(a, b, c, d) check_readback_data_double_(__LINE__, a, b, c, d)
|
|
|
|
static inline void check_readback_data_double_(unsigned int line, const struct resource_readback *rb,
|
|
|
|
const RECT *rect, double expected, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
RECT r = {0, 0, rb->width, rb->height};
|
|
|
|
unsigned int x = 0, y;
|
|
|
|
bool all_match = true;
|
|
|
|
double got = 0;
|
|
|
|
|
|
|
|
if (rect)
|
|
|
|
r = *rect;
|
|
|
|
|
|
|
|
for (y = r.top; y < r.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = r.left; x < r.right; ++x)
|
|
|
|
{
|
|
|
|
got = get_readback_double(rb, x, y);
|
|
|
|
if (!compare_double(got, expected, max_diff))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got %.15le, expected %.15le at (%u, %u).\n", got, expected, x, y);
|
|
|
|
}
|
|
|
|
|
2023-10-13 14:27:44 -07:00
|
|
|
#define check_readback_data_uint(a, b, c, d) check_readback_data_uint_(__LINE__, a, b, c, d)
|
|
|
|
static inline void check_readback_data_uint_(unsigned int line, struct resource_readback *rb,
|
|
|
|
const D3D12_BOX *box, unsigned int expected, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
D3D12_BOX b = {0, 0, 0, rb->width, rb->height, rb->depth};
|
|
|
|
unsigned int x = 0, y = 0, z;
|
|
|
|
bool all_match = true;
|
|
|
|
unsigned int got = 0;
|
|
|
|
|
|
|
|
if (box)
|
|
|
|
b = *box;
|
|
|
|
|
|
|
|
for (z = b.front; z < b.back; ++z)
|
|
|
|
{
|
|
|
|
for (y = b.top; y < b.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = b.left; x < b.right; ++x)
|
|
|
|
{
|
|
|
|
got = get_readback_uint(rb, x, y, z);
|
|
|
|
if (!compare_color(got, expected, max_diff))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got 0x%08x, expected 0x%08x at (%u, %u, %u).\n", got, expected, x, y, z);
|
|
|
|
}
|
|
|
|
|
2024-02-25 20:31:54 -08:00
|
|
|
#define check_readback_data_uint64(a, b, c, d) check_readback_data_uint64_(__LINE__, a, b, c, d)
|
|
|
|
static inline void check_readback_data_uint64_(unsigned int line, struct resource_readback *rb,
|
|
|
|
const D3D12_BOX *box, uint64_t expected, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
D3D12_BOX b = {0, 0, 0, rb->width, rb->height, rb->depth};
|
|
|
|
unsigned int x = 0, y = 0;
|
|
|
|
bool all_match = true;
|
|
|
|
uint64_t got = 0;
|
|
|
|
|
|
|
|
if (box)
|
|
|
|
b = *box;
|
|
|
|
|
|
|
|
for (y = b.top; y < b.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = b.left; x < b.right; ++x)
|
|
|
|
{
|
|
|
|
got = get_readback_uint64(rb, x, y);
|
|
|
|
if (!compare_uint64(got, expected, max_diff))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got 0x%016"PRIx64", expected 0x%016"PRIx64" at (%u, %u).\n", got, expected, x, y);
|
|
|
|
}
|
|
|
|
|
2022-05-17 06:45:40 -07:00
|
|
|
#define check_readback_data_vec4(a, b, c, d) check_readback_data_vec4_(__LINE__, a, b, c, d)
|
|
|
|
static inline void check_readback_data_vec4_(unsigned int line, const struct resource_readback *rb,
|
|
|
|
const RECT *rect, const struct vec4 *expected, unsigned int max_diff)
|
|
|
|
{
|
|
|
|
RECT r = {0, 0, rb->width, rb->height};
|
|
|
|
unsigned int x = 0, y = 0;
|
|
|
|
struct vec4 got = {0};
|
|
|
|
bool all_match = true;
|
|
|
|
|
|
|
|
if (rect)
|
|
|
|
r = *rect;
|
|
|
|
|
|
|
|
for (y = r.top; y < r.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = r.left; x < r.right; ++x)
|
|
|
|
{
|
|
|
|
got = *get_readback_vec4(rb, x, y);
|
|
|
|
if (!compare_vec4(&got, expected, max_diff))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e} at (%u, %u).\n",
|
|
|
|
got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y);
|
|
|
|
}
|
|
|
|
|
2024-01-31 22:02:58 -08:00
|
|
|
#define check_readback_data_ivec4(a, b, c) check_readback_data_uvec4_(__LINE__, a, b, (const struct uvec4 *)(c))
|
2023-10-13 14:27:44 -07:00
|
|
|
#define check_readback_data_uvec4(a, b, c) check_readback_data_uvec4_(__LINE__, a, b, c)
|
|
|
|
static inline void check_readback_data_uvec4_(unsigned int line, const struct resource_readback *rb,
|
|
|
|
const RECT *rect, const struct uvec4 *expected)
|
|
|
|
{
|
|
|
|
RECT r = {0, 0, rb->width, rb->height};
|
|
|
|
unsigned int x = 0, y = 0;
|
|
|
|
struct uvec4 got = {0};
|
|
|
|
bool all_match = true;
|
|
|
|
|
|
|
|
if (rect)
|
|
|
|
r = *rect;
|
|
|
|
|
|
|
|
for (y = r.top; y < r.bottom; ++y)
|
|
|
|
{
|
|
|
|
for (x = r.left; x < r.right; ++x)
|
|
|
|
{
|
|
|
|
got = *get_readback_uvec4(rb, x, y);
|
|
|
|
if (!compare_uvec4(&got, expected))
|
|
|
|
{
|
|
|
|
all_match = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!all_match)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ok_(line)(all_match, "Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x} at (%u, %u).\n",
|
|
|
|
got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y);
|
|
|
|
}
|
|
|
|
|
2023-02-21 15:46:36 -08:00
|
|
|
struct test_options
|
|
|
|
{
|
|
|
|
bool use_warp_device;
|
|
|
|
unsigned int adapter_idx;
|
|
|
|
bool enable_debug_layer;
|
|
|
|
bool enable_gpu_based_validation;
|
|
|
|
const char *filename;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern struct test_options test_options;
|
|
|
|
|
|
|
|
static inline void parse_args(int argc, char **argv)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 1; i < argc; ++i)
|
|
|
|
{
|
|
|
|
if (!strcmp(argv[i], "--warp"))
|
|
|
|
test_options.use_warp_device = true;
|
|
|
|
else if (!strcmp(argv[i], "--adapter") && i + 1 < argc)
|
|
|
|
test_options.adapter_idx = atoi(argv[++i]);
|
|
|
|
else if (!strcmp(argv[i], "--validate"))
|
|
|
|
test_options.enable_debug_layer = true;
|
|
|
|
else if (!strcmp(argv[i], "--gbv"))
|
|
|
|
test_options.enable_gpu_based_validation = true;
|
|
|
|
else if (argv[i][0] != '-')
|
|
|
|
test_options.filename = argv[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-03 19:14:52 -07:00
|
|
|
static inline HRESULT vkd3d_shader_code_from_dxc_blob(IDxcBlob *blob, struct vkd3d_shader_code *blob_out)
|
|
|
|
{
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
size = IDxcBlob_GetBufferSize(blob);
|
|
|
|
if (!(blob_out->code = malloc(size)))
|
|
|
|
{
|
|
|
|
trace("Failed to allocate shader code.\n");
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy((void *)blob_out->code, IDxcBlob_GetBufferPointer(blob), size);
|
|
|
|
blob_out->size = size;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline HRESULT dxc_compile(void *dxc_compiler, const WCHAR *profile,
|
|
|
|
unsigned int compile_options, const char *hlsl, struct vkd3d_shader_code *blob_out)
|
|
|
|
{
|
|
|
|
DxcBuffer src_buf = {hlsl, strlen(hlsl), 65001};
|
|
|
|
IDxcCompiler3 *compiler = dxc_compiler;
|
|
|
|
IDxcBlobUtf8 *errors;
|
|
|
|
IDxcResult *result;
|
|
|
|
HRESULT compile_hr;
|
|
|
|
size_t arg_count;
|
|
|
|
IDxcBlob *blob;
|
|
|
|
int hr;
|
|
|
|
|
|
|
|
const WCHAR *args[] =
|
|
|
|
{
|
|
|
|
L"/T",
|
|
|
|
profile,
|
|
|
|
L"/Qstrip_reflect",
|
|
|
|
L"/Qstrip_debug",
|
|
|
|
L"/flegacy-macro-expansion",
|
|
|
|
L"/flegacy-resource-reservation",
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
memset(blob_out, 0, sizeof(*blob_out));
|
|
|
|
|
|
|
|
arg_count = ARRAY_SIZE(args) - 3;
|
|
|
|
if (compile_options & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR)
|
|
|
|
args[arg_count++] = L"/Zpr";
|
|
|
|
if (compile_options & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR)
|
|
|
|
args[arg_count++] = L"/Zpc";
|
|
|
|
if (compile_options & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY)
|
|
|
|
args[arg_count++] = L"/Gec";
|
|
|
|
|
|
|
|
if (FAILED(hr = IDxcCompiler3_Compile(compiler, &src_buf, args,
|
|
|
|
arg_count, NULL, &IID_IDxcResult, (void **)&result)))
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
if (IDxcResult_HasOutput(result, DXC_OUT_ERRORS)
|
|
|
|
&& SUCCEEDED(hr = IDxcResult_GetOutput(result, DXC_OUT_ERRORS, &IID_IDxcBlobUtf8, (void **)&errors, NULL)))
|
|
|
|
{
|
|
|
|
if (IDxcBlobUtf8_GetStringLength(errors) && vkd3d_test_state.debug_level)
|
|
|
|
trace("%s\n", (char *)IDxcBlobUtf8_GetStringPointer(errors));
|
|
|
|
IDxcBlobUtf8_Release(errors);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr = IDxcResult_GetStatus(result, &compile_hr)) || FAILED((hr = compile_hr)))
|
|
|
|
{
|
|
|
|
if (hr == DXC_E_LLVM_CAST_ERROR)
|
|
|
|
hr = E_FAIL;
|
|
|
|
goto result_release;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr = IDxcResult_GetOutput(result, DXC_OUT_OBJECT, &IID_IDxcBlob, (void **)&blob, NULL)))
|
|
|
|
goto result_release;
|
|
|
|
|
|
|
|
IDxcResult_Release(result);
|
|
|
|
|
|
|
|
hr = vkd3d_shader_code_from_dxc_blob(blob, blob_out);
|
|
|
|
IDxcBlob_Release(blob);
|
|
|
|
return hr;
|
|
|
|
|
|
|
|
result_release:
|
|
|
|
IDxcResult_Release(result);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if (defined(SONAME_LIBDXCOMPILER) || defined(VKD3D_CROSSTEST))
|
|
|
|
static inline IDxcCompiler3 *dxcompiler_create(void)
|
|
|
|
{
|
|
|
|
DxcCreateInstanceProc create_instance;
|
|
|
|
IDxcCompiler3 *compiler;
|
|
|
|
const char *skip_dxc;
|
|
|
|
void *dll;
|
|
|
|
int hr;
|
|
|
|
|
|
|
|
if ((skip_dxc = getenv("VKD3D_TEST_SKIP_DXC")) && strcmp(skip_dxc, "") != 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
# ifdef VKD3D_CROSSTEST
|
|
|
|
dll = vkd3d_dlopen("dxcompiler.dll");
|
|
|
|
# else
|
|
|
|
dll = vkd3d_dlopen(SONAME_LIBDXCOMPILER);
|
|
|
|
# endif
|
|
|
|
ok(dll, "Failed to load dxcompiler library, %s.\n", vkd3d_dlerror());
|
|
|
|
if (!dll)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
create_instance = (DxcCreateInstanceProc)vkd3d_dlsym(dll, "DxcCreateInstance");
|
|
|
|
ok(create_instance, "Failed to get DxcCreateInstance() pointer.\n");
|
|
|
|
if (!create_instance)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hr = create_instance(&CLSID_DxcCompiler, &IID_IDxcCompiler3, (void **)&compiler);
|
|
|
|
ok(SUCCEEDED(hr), "Failed to create instance, hr %#x.\n", hr);
|
|
|
|
if (FAILED(hr))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return compiler;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline IDxcCompiler3 *dxcompiler_create(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-01-26 17:40:28 -08:00
|
|
|
#endif
|