Files
vkd3d/demos/demo.h
2025-06-24 15:24:16 +02:00

307 lines
8.5 KiB
C

/*
* Copyright 2016 Henri Verbeet for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* 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
#include <vkd3d_windows.h>
#define WIDL_C_INLINE_WRAPPERS
#define COBJMACROS
#include <vkd3d_d3d12.h>
#include <inttypes.h>
#include <math.h>
#ifdef __WIN32__
#define DEMO_ASM_PUSHSECTION ".section rdata\n\t"
#define DEMO_ASM_POPSECTION ".text\n\t"
#define DEMO_ASM_OBJECT_TYPE(name)
#elif defined(__APPLE__)
#define DEMO_ASM_PUSHSECTION ".pushsection __TEXT,__const\n\t"
#define DEMO_ASM_POPSECTION ".popsection\n\t"
#define DEMO_ASM_OBJECT_TYPE(name)
#else
#define DEMO_ASM_PUSHSECTION ".pushsection .rodata\n\t"
#define DEMO_ASM_POPSECTION ".popsection\n\t"
#define DEMO_ASM_OBJECT_TYPE(name) ".type "name", @object\n\t"
#endif
#if (defined(__WIN32__) && defined(__i386__)) || defined(__APPLE__)
#define DEMO_ASM_NAME(name) "_"#name
#else
#define DEMO_ASM_NAME(name) #name
#endif
#define DEMO_EMBED_ASM(name, file) \
DEMO_ASM_PUSHSECTION \
".global "name"\n\t" \
DEMO_ASM_OBJECT_TYPE(name) \
".balign 8\n\t" \
name":\n\t" \
".incbin \""file"\"\n\t" \
name"_end:\n\t" \
".global "name"_size\n\t" \
DEMO_ASM_OBJECT_TYPE(name"_size") \
".balign 8\n\t" \
name"_size:\n\t" \
".int "name"_end - "name"\n\t" \
DEMO_ASM_POPSECTION
#define DEMO_EMBED(name, file) \
extern const unsigned int name##_size; \
extern const uint8_t name[]; \
__asm__(DEMO_EMBED_ASM(DEMO_ASM_NAME(name), file))
#if defined(__GNUC__) || defined(__clang__)
# ifdef __MINGW_PRINTF_FORMAT
# define DEMO_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))
# else
# define DEMO_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))
# endif
#else
# define DEMO_PRINTF_FUNC(fmt, args)
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
#define DEMO_KEY_UNKNOWN 0x0000
#define DEMO_KEY_ESCAPE 0xff1b
#define DEMO_KEY_LEFT 0xff51
#define DEMO_KEY_UP 0xff52
#define DEMO_KEY_RIGHT 0xff53
#define DEMO_KEY_DOWN 0xff54
#define DEMO_KEY_KP_ADD 0xffab
#define DEMO_KEY_KP_SUBTRACT 0xffad
#define DEMO_KEY_F1 0xffbe
struct demo_vec3
{
float x, y, z;
};
struct demo_vec4
{
float x, y, z, w;
};
struct demo_uvec2
{
uint32_t x, y;
};
struct demo_uvec4
{
uint32_t x, y, z, w;
};
struct demo_matrix
{
float m[4][4];
};
struct demo_patch
{
uint16_t p[4][4];
};
struct demo_swapchain_desc
{
unsigned int width;
unsigned int height;
unsigned int buffer_count;
DXGI_FORMAT format;
};
typedef uint32_t demo_key;
static inline void demo_vec3_set(struct demo_vec3 *v, float x, float y, float z)
{
v->x = x;
v->y = y;
v->z = z;
}
static inline void demo_vec3_subtract(struct demo_vec3 *v, const struct demo_vec3 *a, const struct demo_vec3 *b)
{
demo_vec3_set(v, a->x - b->x, a->y - b->y, a->z - b->z);
}
static inline float demo_vec3_dot(const struct demo_vec3 *a, const struct demo_vec3 *b)
{
return a->x * b->x + a->y * b->y + a->z * b->z;
}
static inline float demo_vec3_length(const struct demo_vec3 *v)
{
return sqrtf(demo_vec3_dot(v, v));
}
static inline void demo_vec3_scale(struct demo_vec3 *v, const struct demo_vec3 *a, float s)
{
demo_vec3_set(v, a->x * s, a->y * s, a->z *s);
}
static inline void demo_vec3_normalise(struct demo_vec3 *v, const struct demo_vec3 *a)
{
demo_vec3_scale(v, a, 1.0f / demo_vec3_length(a));
}
static inline void demo_vec3_cross(struct demo_vec3 *v, const struct demo_vec3 *a, const struct demo_vec3 *b)
{
demo_vec3_set(v, a->y * b->z - a->z * b->y, a->z * b->x - a->x * b->z, a->x * b->y - a->y * b->x);
}
static inline void demo_vec4_set(struct demo_vec4 *v, float x, float y, float z, float w)
{
v->x = x;
v->y = y;
v->z = z;
v->w = w;
}
static inline void demo_matrix_look_at_rh(struct demo_matrix *m, const struct demo_vec3 *eye,
const struct demo_vec3 *ref, const struct demo_vec3 *up)
{
struct demo_vec3 f, s, t, u;
demo_vec3_subtract(&f, eye, ref);
demo_vec3_normalise(&f, &f);
demo_vec3_cross(&s, up, &f);
demo_vec3_normalise(&s, &s);
demo_vec3_cross(&u, &f, &s);
demo_vec3_set(&t, demo_vec3_dot(&s, eye), demo_vec3_dot(&u, eye), demo_vec3_dot(&f, eye));
*m = (struct demo_matrix)
{{
{ s.x, u.x, f.x, 0.0f},
{ s.y, u.y, f.y, 0.0f},
{ s.z, u.z, f.z, 0.0f},
{-t.x, -t.y, -t.z, 1.0f},
}};
}
static inline void demo_matrix_multiply(struct demo_matrix *out,
const struct demo_matrix *a, const struct demo_matrix *b)
{
unsigned int i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
out->m[i][j] = a->m[i][0] * b->m[0][j]
+ a->m[i][1] * b->m[1][j]
+ a->m[i][2] * b->m[2][j]
+ a->m[i][3] * b->m[3][j];
}
}
}
static inline void demo_matrix_perspective_rh(struct demo_matrix *m, float w, float h, float z_near, float z_far)
{
float sx = 2.0 * z_near / w;
float sy = 2.0 * z_near / h;
float sz = z_far / (z_near - z_far);
float d = z_near * sz;
*m = (struct demo_matrix)
{{
{ sx, 0.0f, 0.0f, 0.0f},
{0.0f, sy, 0.0f, 0.0f},
{0.0f, 0.0f, sz, -1.0f},
{0.0f, 0.0f, d, 0.0f},
}};
}
static inline void demo_rasterizer_desc_init_default(D3D12_RASTERIZER_DESC *desc)
{
desc->FillMode = D3D12_FILL_MODE_SOLID;
desc->CullMode = D3D12_CULL_MODE_BACK;
desc->FrontCounterClockwise = FALSE;
desc->DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
desc->DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
desc->SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
desc->DepthClipEnable = TRUE;
desc->MultisampleEnable = FALSE;
desc->AntialiasedLineEnable = FALSE;
desc->ForcedSampleCount = 0;
desc->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
}
static inline void demo_blend_desc_init_default(D3D12_BLEND_DESC *desc)
{
static const D3D12_RENDER_TARGET_BLEND_DESC rt_blend_desc =
{
.BlendEnable = FALSE,
.LogicOpEnable = FALSE,
.SrcBlend = D3D12_BLEND_ONE,
.DestBlend = D3D12_BLEND_ZERO,
.BlendOp = D3D12_BLEND_OP_ADD,
.SrcBlendAlpha = D3D12_BLEND_ONE,
.DestBlendAlpha = D3D12_BLEND_ZERO,
.BlendOpAlpha = D3D12_BLEND_OP_ADD,
.LogicOp = D3D12_LOGIC_OP_NOOP,
.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL,
};
unsigned int i;
desc->AlphaToCoverageEnable = FALSE;
desc->IndependentBlendEnable = FALSE;
for (i = 0; i < ARRAY_SIZE(desc->RenderTarget); ++i)
{
desc->RenderTarget[i] = rt_blend_desc;
}
}
static inline HRESULT demo_create_root_signature(ID3D12Device *device,
const D3D12_ROOT_SIGNATURE_DESC *desc, ID3D12RootSignature **signature)
{
ID3DBlob *blob;
HRESULT hr;
if (FAILED(hr = D3D12SerializeRootSignature(desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL)))
return hr;
hr = ID3D12Device_CreateRootSignature(device, 0, ID3D10Blob_GetBufferPointer(blob),
ID3D10Blob_GetBufferSize(blob), &IID_ID3D12RootSignature, (void **)signature);
ID3D10Blob_Release(blob);
return hr;
}
#ifdef VKD3D_CROSSTEST
#include "demo_d3d12.h"
#else
# ifndef _WIN32
# define INFINITE VKD3D_INFINITE
# endif
#include "demo_vkd3d.h"
#endif