mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
demos/triangle: Add a demo program.
This commit is contained in:
parent
6cbe8626c2
commit
fa5b972371
46
Makefile.am
46
Makefile.am
@ -19,11 +19,29 @@ vkd3d_public_headers = \
|
|||||||
include/vkd3d_utils.h \
|
include/vkd3d_utils.h \
|
||||||
include/vkd3d_windows.h
|
include/vkd3d_windows.h
|
||||||
|
|
||||||
|
spv_triangle_shaders = \
|
||||||
|
demos/triangle.vert.spv \
|
||||||
|
demos/triangle.frag.spv
|
||||||
|
|
||||||
|
spv_shaders = \
|
||||||
|
$(spv_triangle_shaders)
|
||||||
|
|
||||||
|
hlsl_shaders = \
|
||||||
|
demos/triangle.hlsl
|
||||||
|
|
||||||
vkd3d_tests = \
|
vkd3d_tests = \
|
||||||
tests/d3d12
|
tests/d3d12
|
||||||
|
|
||||||
|
vkd3d_demos = \
|
||||||
|
demos/triangle
|
||||||
|
|
||||||
|
vkd3d_demos_headers = \
|
||||||
|
demos/demo.h \
|
||||||
|
demos/demo_win32.h \
|
||||||
|
demos/demo_xcb.h
|
||||||
|
|
||||||
BUILT_SOURCES = $(widl_headers)
|
BUILT_SOURCES = $(widl_headers)
|
||||||
CLEANFILES = $(widl_headers)
|
CLEANFILES = $(widl_headers) $(spv_shaders)
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libvkd3d-common.la
|
noinst_LTLIBRARIES = libvkd3d-common.la
|
||||||
libvkd3d_common_la_SOURCES = \
|
libvkd3d_common_la_SOURCES = \
|
||||||
@ -66,6 +84,11 @@ AM_DEFAULT_SOURCE_EXT = .c
|
|||||||
TESTS = $(vkd3d_tests)
|
TESTS = $(vkd3d_tests)
|
||||||
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@
|
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@
|
||||||
|
|
||||||
|
noinst_PROGRAMS = $(vkd3d_demos)
|
||||||
|
EXTRA_DIST += $(vkd3d_demos_headers)
|
||||||
|
EXTRA_demos_triangle_DEPENDENCIES = $(spv_triangle_shaders)
|
||||||
|
demos_triangle_LDADD = libvkd3d.la $(LDADD) @XCB_LIBS@
|
||||||
|
|
||||||
VKD3D_V_WIDL = $(vkd3d_v_widl_@AM_V@)
|
VKD3D_V_WIDL = $(vkd3d_v_widl_@AM_V@)
|
||||||
vkd3d_v_widl_ = $(vkd3d_v_widl_@AM_DEFAULT_V@)
|
vkd3d_v_widl_ = $(vkd3d_v_widl_@AM_DEFAULT_V@)
|
||||||
vkd3d_v_widl_0 = @echo " WIDL " $@;
|
vkd3d_v_widl_0 = @echo " WIDL " $@;
|
||||||
@ -75,6 +98,17 @@ EXTRA_DIST += $(widl_headers) $(widl_headers:.h=.idl)
|
|||||||
$(widl_headers): %.h: %.idl
|
$(widl_headers): %.h: %.idl
|
||||||
$(VKD3D_V_WIDL)$(WIDL) -o $@ $<
|
$(VKD3D_V_WIDL)$(WIDL) -o $@ $<
|
||||||
|
|
||||||
|
VKD3D_V_GLSLANG = $(vkd3d_v_glslang_@AM_V@)
|
||||||
|
vkd3d_v_glslang_ = $(vkd3d_v_glslang_@AM_DEFAULT_V@)
|
||||||
|
vkd3d_v_glslang_0 = @echo " GLSLANG " $@;
|
||||||
|
vkd3d_v_glslang_1 =
|
||||||
|
|
||||||
|
EXTRA_DIST += $(spv_shaders:.spv=)
|
||||||
|
$(spv_shaders): %.spv: %
|
||||||
|
$(VKD3D_V_GLSLANG)$(GLSLANG) -V -o $@ $<
|
||||||
|
|
||||||
|
EXTRA_DIST += $(hlsl_shaders)
|
||||||
|
|
||||||
libvkd3d.pc: $(srcdir)/libs/vkd3d/libvkd3d.pc.in
|
libvkd3d.pc: $(srcdir)/libs/vkd3d/libvkd3d.pc.in
|
||||||
sed -e 's![@]prefix[@]!$(prefix)!g' \
|
sed -e 's![@]prefix[@]!$(prefix)!g' \
|
||||||
-e 's![@]exec_prefix[@]!$(exec_prefix)!g' \
|
-e 's![@]exec_prefix[@]!$(exec_prefix)!g' \
|
||||||
@ -93,13 +127,14 @@ if HAS_CROSSTARGET32
|
|||||||
CROSS32_CC = @CROSSCC32@
|
CROSS32_CC = @CROSSCC32@
|
||||||
CROSS32_DLLTOOL = @CROSSTARGET32@-dlltool
|
CROSS32_DLLTOOL = @CROSSTARGET32@-dlltool
|
||||||
CROSS32_IMPLIBS = $(cross_implibs:=.cross32.a)
|
CROSS32_IMPLIBS = $(cross_implibs:=.cross32.a)
|
||||||
CROSS32_EXEFILES = $(vkd3d_tests:=.cross32.exe)
|
CROSS32_EXEFILES = $(vkd3d_tests:=.cross32.exe) $(vkd3d_demos:=.cross32.exe)
|
||||||
CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES)
|
CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES)
|
||||||
|
|
||||||
CLEANFILES += $(CROSS32_FILES)
|
CLEANFILES += $(CROSS32_FILES)
|
||||||
crosstest32: $(CROSS32_FILES)
|
crosstest32: $(CROSS32_FILES)
|
||||||
|
|
||||||
-include tests/$(DEPDIR)/*.cross32.Po
|
-include tests/$(DEPDIR)/*.cross32.Po
|
||||||
|
-include demos/$(DEPDIR)/*.cross32.Po
|
||||||
|
|
||||||
$(CROSS32_IMPLIBS): %.cross32.a: %.cross32.def
|
$(CROSS32_IMPLIBS): %.cross32.a: %.cross32.def
|
||||||
@${MKDIR_P} crosslibs
|
@${MKDIR_P} crosslibs
|
||||||
@ -107,7 +142,7 @@ $(CROSS32_IMPLIBS): %.cross32.a: %.cross32.def
|
|||||||
|
|
||||||
$(CROSS32_EXEFILES): %.cross32.exe: %.c $(CROSS32_IMPLIBS) $(widl_headers)
|
$(CROSS32_EXEFILES): %.cross32.exe: %.c $(CROSS32_IMPLIBS) $(widl_headers)
|
||||||
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
||||||
$(CROSS32_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS32_IMPLIBS) && \
|
$(CROSS32_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS32_IMPLIBS) -ldxgi -lgdi32 && \
|
||||||
$(am__mv) $$depbase.Tpo $$depbase.Po
|
$(am__mv) $$depbase.Tpo $$depbase.Po
|
||||||
else
|
else
|
||||||
crosstest32:
|
crosstest32:
|
||||||
@ -117,13 +152,14 @@ if HAS_CROSSTARGET64
|
|||||||
CROSS64_CC = @CROSSCC64@
|
CROSS64_CC = @CROSSCC64@
|
||||||
CROSS64_DLLTOOL = @CROSSTARGET64@-dlltool
|
CROSS64_DLLTOOL = @CROSSTARGET64@-dlltool
|
||||||
CROSS64_IMPLIBS = $(cross_implibs:=.cross64.a)
|
CROSS64_IMPLIBS = $(cross_implibs:=.cross64.a)
|
||||||
CROSS64_EXEFILES = $(vkd3d_tests:=.cross64.exe)
|
CROSS64_EXEFILES = $(vkd3d_tests:=.cross64.exe) $(vkd3d_demos:=.cross64.exe)
|
||||||
CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES)
|
CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES)
|
||||||
|
|
||||||
CLEANFILES += $(CROSS64_FILES)
|
CLEANFILES += $(CROSS64_FILES)
|
||||||
crosstest64: $(CROSS64_FILES)
|
crosstest64: $(CROSS64_FILES)
|
||||||
|
|
||||||
-include tests/$(DEPDIR)/*.cross64.Po
|
-include tests/$(DEPDIR)/*.cross64.Po
|
||||||
|
-include demos/$(DEPDIR)/*.cross64.Po
|
||||||
|
|
||||||
$(CROSS64_IMPLIBS): %.cross64.a: %.cross64.def
|
$(CROSS64_IMPLIBS): %.cross64.a: %.cross64.def
|
||||||
@${MKDIR_P} crosslibs
|
@${MKDIR_P} crosslibs
|
||||||
@ -131,7 +167,7 @@ $(CROSS64_IMPLIBS): %.cross64.a: %.cross64.def
|
|||||||
|
|
||||||
$(CROSS64_EXEFILES): %.cross64.exe: %.c $(CROSS64_IMPLIBS) $(widl_headers)
|
$(CROSS64_EXEFILES): %.cross64.exe: %.c $(CROSS64_IMPLIBS) $(widl_headers)
|
||||||
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
||||||
$(CROSS64_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS64_IMPLIBS) && \
|
$(CROSS64_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS64_IMPLIBS) -ldxgi -lgdi32 && \
|
||||||
$(am__mv) $$depbase.Tpo $$depbase.Po
|
$(am__mv) $$depbase.Tpo $$depbase.Po
|
||||||
else
|
else
|
||||||
crosstest64:
|
crosstest64:
|
||||||
|
@ -7,6 +7,7 @@ AC_CONFIG_LIBOBJ_DIR([portable])
|
|||||||
AC_CONFIG_HEADERS(include/config.h)
|
AC_CONFIG_HEADERS(include/config.h)
|
||||||
|
|
||||||
AC_ARG_VAR([WIDL], [widl IDL compiler])
|
AC_ARG_VAR([WIDL], [widl IDL compiler])
|
||||||
|
AC_ARG_VAR([GLSLANG], [glslangValidator GLSL compiler])
|
||||||
AC_ARG_VAR([CROSSCC32], [32-bit Windows cross compiler])
|
AC_ARG_VAR([CROSSCC32], [32-bit Windows cross compiler])
|
||||||
AC_ARG_VAR([CROSSCC64], [64-bit Windows cross compiler])
|
AC_ARG_VAR([CROSSCC64], [64-bit Windows cross compiler])
|
||||||
|
|
||||||
@ -17,8 +18,9 @@ AM_PROG_CC_C_O
|
|||||||
AC_PROG_SED
|
AC_PROG_SED
|
||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
AC_CHECK_PROG([WIDL], [widl], [widl], [no])
|
AC_CHECK_PROG([WIDL], [widl], [widl], [no])
|
||||||
|
|
||||||
AS_IF([test "x$WIDL" = "xno"], [AC_MSG_ERROR([widl is required to build header files.])])
|
AS_IF([test "x$WIDL" = "xno"], [AC_MSG_ERROR([widl is required to build header files.])])
|
||||||
|
AC_CHECK_PROG([GLSLANG], [glslangValidator], [glslang], [no])
|
||||||
|
AS_IF([test "x$GLSLANG" = "xno"], [AC_MSG_ERROR([glslangValidator is required to compile shaders.])])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign silent-rules subdir-objects no-dist-gzip dist-xz -Wall -Werror])
|
AM_INIT_AUTOMAKE([1.11 foreign silent-rules subdir-objects no-dist-gzip dist-xz -Wall -Werror])
|
||||||
AM_MAINTAINER_MODE([enable])
|
AM_MAINTAINER_MODE([enable])
|
||||||
@ -52,6 +54,11 @@ AC_CHECK_LIB([pthread], [pthread_create],
|
|||||||
[AC_SUBST(PTHREAD_LIBS, "-lpthread")],
|
[AC_SUBST(PTHREAD_LIBS, "-lpthread")],
|
||||||
[AC_MSG_ERROR(libpthread not found.)])
|
[AC_MSG_ERROR(libpthread not found.)])
|
||||||
|
|
||||||
|
AC_ARG_VAR([XCB_LIBS], [linker flags for xcb])
|
||||||
|
AC_CHECK_LIB([xcb], [xcb_connect],
|
||||||
|
[AC_SUBST(XCB_LIBS, "-lxcb")],
|
||||||
|
[AC_MSG_ERROR([libxcb not found.])])
|
||||||
|
|
||||||
AC_CHECK_LIB([vulkan], [vkGetInstanceProcAddr], [], [AC_MSG_ERROR([libvulkan not found.])])
|
AC_CHECK_LIB([vulkan], [vkGetInstanceProcAddr], [], [AC_MSG_ERROR([libvulkan not found.])])
|
||||||
|
|
||||||
dnl Check for functions
|
dnl Check for functions
|
||||||
|
2
demos/.gitignore
vendored
Normal file
2
demos/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
triangle
|
||||||
|
*.spv
|
110
demos/demo.h
Normal file
110
demos/demo.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Henri Verbeet for CodeWeavers
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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 <d3d12.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
||||||
|
|
||||||
|
struct demo_vec3
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_vec4
|
||||||
|
{
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_swapchain_desc
|
||||||
|
{
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned int buffer_count;
|
||||||
|
DXGI_FORMAT format;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "demo_win32.h"
|
||||||
|
#else
|
||||||
|
#include <vkd3d_utils.h>
|
||||||
|
#include "demo_xcb.h"
|
||||||
|
#endif
|
302
demos/demo_win32.h
Normal file
302
demos/demo_win32.h
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Józef Kucia for CodeWeavers
|
||||||
|
* Copyright 2016 Henri Verbeet for CodeWeavers
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dxgi1_4.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define DEMO_WINDOW_CLASS_NAME L"demo_wc"
|
||||||
|
|
||||||
|
struct demo
|
||||||
|
{
|
||||||
|
HMODULE d3dcompiler;
|
||||||
|
HRESULT (WINAPI *compile_from_file)(const WCHAR *filename, const void *defines, void *include,
|
||||||
|
const char *entry_point, const char *profile, UINT flags1, UINT flags2,
|
||||||
|
ID3DBlob **code, ID3DBlob **errors);
|
||||||
|
size_t window_count;
|
||||||
|
bool quit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_window
|
||||||
|
{
|
||||||
|
HINSTANCE instance;
|
||||||
|
HWND hwnd;
|
||||||
|
struct demo *demo;
|
||||||
|
void *user_data;
|
||||||
|
void (*draw_func)(void *user_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_swapchain
|
||||||
|
{
|
||||||
|
IDXGISwapChain3 *swapchain;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct demo_window *demo_window_create(struct demo *demo, const char *title,
|
||||||
|
unsigned int width, unsigned int height, void (*draw_func)(void *user_data), void *user_data)
|
||||||
|
{
|
||||||
|
RECT rect = {0, 0, width, height};
|
||||||
|
struct demo_window *window;
|
||||||
|
int title_size;
|
||||||
|
WCHAR *title_w;
|
||||||
|
DWORD style;
|
||||||
|
|
||||||
|
if (!(window = malloc(sizeof(*window))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
title_size = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
|
||||||
|
if (!(title_w = calloc(title_size, sizeof(*title_w))))
|
||||||
|
{
|
||||||
|
free(window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, title_size);
|
||||||
|
|
||||||
|
window->instance = GetModuleHandle(NULL);
|
||||||
|
window->draw_func = draw_func;
|
||||||
|
window->user_data = user_data;
|
||||||
|
|
||||||
|
style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
|
||||||
|
AdjustWindowRect(&rect, style, FALSE);
|
||||||
|
window->hwnd = CreateWindowExW(0, DEMO_WINDOW_CLASS_NAME, title_w, style, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, window->instance, NULL);
|
||||||
|
free(title_w);
|
||||||
|
if (!window->hwnd)
|
||||||
|
{
|
||||||
|
free(window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SetWindowLongPtrW(window->hwnd, GWLP_USERDATA, (LONG_PTR)window);
|
||||||
|
window->demo = demo;
|
||||||
|
++demo->window_count;
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_window_destroy(struct demo_window *window)
|
||||||
|
{
|
||||||
|
if (window->hwnd)
|
||||||
|
DestroyWindow(window->hwnd);
|
||||||
|
if (!--window->demo->window_count)
|
||||||
|
window->demo->quit = true;
|
||||||
|
free(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline LRESULT CALLBACK demo_window_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
struct demo_window *window = (void *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||||||
|
|
||||||
|
switch (message)
|
||||||
|
{
|
||||||
|
case WM_PAINT:
|
||||||
|
if (window && window->draw_func)
|
||||||
|
window->draw_func(window->user_data);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
window->hwnd = NULL;
|
||||||
|
demo_window_destroy(window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProcW(hwnd, message, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_process_events(struct demo *demo)
|
||||||
|
{
|
||||||
|
MSG msg = {0};
|
||||||
|
|
||||||
|
while (GetMessage(&msg, NULL, 0, 0) != -1)
|
||||||
|
{
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
break;
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
if (demo->quit)
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool demo_init(struct demo *demo)
|
||||||
|
{
|
||||||
|
WNDCLASSEXW wc;
|
||||||
|
|
||||||
|
if (!(demo->d3dcompiler = LoadLibraryW(L"d3dcompiler_47")))
|
||||||
|
return false;
|
||||||
|
if (!(demo->compile_from_file = (void *)GetProcAddress(demo->d3dcompiler, "D3DCompileFromFile")))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
wc.cbSize = sizeof(wc);
|
||||||
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wc.lpfnWndProc = demo_window_proc;
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hInstance = GetModuleHandle(NULL);
|
||||||
|
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
|
||||||
|
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
||||||
|
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||||
|
wc.lpszMenuName = NULL;
|
||||||
|
wc.lpszClassName = DEMO_WINDOW_CLASS_NAME;
|
||||||
|
wc.hIconSm = LoadIconW(NULL, IDI_WINLOGO);
|
||||||
|
if (!RegisterClassExW(&wc))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
demo->quit = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
FreeLibrary(demo->d3dcompiler);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_cleanup(struct demo *demo)
|
||||||
|
{
|
||||||
|
UnregisterClassW(DEMO_WINDOW_CLASS_NAME, GetModuleHandle(NULL));
|
||||||
|
FreeLibrary(demo->d3dcompiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *command_queue,
|
||||||
|
struct demo_window *window, const struct demo_swapchain_desc *desc)
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 swapchain_desc;
|
||||||
|
struct demo_swapchain *swapchain;
|
||||||
|
IDXGISwapChain1 *swapchain1;
|
||||||
|
IDXGIFactory2 *factory;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (!(swapchain = malloc(sizeof(*swapchain))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (FAILED(CreateDXGIFactory1(&IID_IDXGIFactory2, (void **)&factory)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
memset(&swapchain_desc, 0, sizeof(swapchain_desc));
|
||||||
|
swapchain_desc.BufferCount = desc->buffer_count;
|
||||||
|
swapchain_desc.Width = desc->width;
|
||||||
|
swapchain_desc.Height = desc->height;
|
||||||
|
swapchain_desc.Format = desc->format;
|
||||||
|
swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
swapchain_desc.SampleDesc.Count = 1;
|
||||||
|
|
||||||
|
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown *)command_queue,
|
||||||
|
window->hwnd, &swapchain_desc, NULL, NULL, &swapchain1);
|
||||||
|
IDXGIFactory2_Release(factory);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain3, (void **)&swapchain->swapchain);
|
||||||
|
IDXGISwapChain1_Release(swapchain1);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return swapchain;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(swapchain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int demo_swapchain_get_current_back_buffer_index(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
return IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain->swapchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ID3D12Resource *demo_swapchain_get_back_buffer(struct demo_swapchain *swapchain, unsigned int index)
|
||||||
|
{
|
||||||
|
ID3D12Resource *buffer;
|
||||||
|
|
||||||
|
if (FAILED(IDXGISwapChain3_GetBuffer(swapchain->swapchain, index,
|
||||||
|
&IID_ID3D12Resource, (void **)&buffer)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_swapchain_present(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
IDXGISwapChain3_Present(swapchain->swapchain, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
IDXGISwapChain3_Release(swapchain->swapchain);
|
||||||
|
free(swapchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline HANDLE demo_create_event(void)
|
||||||
|
{
|
||||||
|
return CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int demo_wait_event(HANDLE event, unsigned int ms)
|
||||||
|
{
|
||||||
|
return WaitForSingleObject(event, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_destroy_event(HANDLE event)
|
||||||
|
{
|
||||||
|
CloseHandle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool demo_load_shader(struct demo *demo, const wchar_t *hlsl_name, const char *entry_point,
|
||||||
|
const char *profile, const char *spv_name, D3D12_SHADER_BYTECODE *shader)
|
||||||
|
{
|
||||||
|
ID3D10Blob *blob, *errors;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = demo->compile_from_file(hlsl_name, NULL, NULL, entry_point, profile, 0, 0, &blob, &errors);
|
||||||
|
if (errors)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%.*s\n", (int)ID3D10Blob_GetBufferSize(errors), (char *)ID3D10Blob_GetBufferPointer(errors));
|
||||||
|
ID3D10Blob_Release(errors);
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
shader->BytecodeLength = ID3D10Blob_GetBufferSize(blob);
|
||||||
|
if (!(shader->pShaderBytecode = malloc(shader->BytecodeLength)))
|
||||||
|
{
|
||||||
|
ID3D10Blob_Release(blob);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void *)shader->pShaderBytecode, ID3D10Blob_GetBufferPointer(blob), shader->BytecodeLength);
|
||||||
|
|
||||||
|
ID3D10Blob_Release(blob);
|
||||||
|
return true;
|
||||||
|
}
|
543
demos/demo_xcb.h
Normal file
543
demos/demo_xcb.h
Normal file
@ -0,0 +1,543 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Józef Kucia for CodeWeavers
|
||||||
|
* Copyright 2016 Henri Verbeet for CodeWeavers
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VK_USE_PLATFORM_XCB_KHR
|
||||||
|
#include <vkd3d.h>
|
||||||
|
#include <xcb/xcb_event.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
|
||||||
|
struct demo
|
||||||
|
{
|
||||||
|
xcb_connection_t *connection;
|
||||||
|
xcb_atom_t wm_protocols_atom;
|
||||||
|
xcb_atom_t wm_delete_window_atom;
|
||||||
|
|
||||||
|
struct demo_window **windows;
|
||||||
|
size_t windows_size;
|
||||||
|
size_t window_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_window
|
||||||
|
{
|
||||||
|
xcb_window_t window;
|
||||||
|
struct demo *demo;
|
||||||
|
|
||||||
|
void *user_data;
|
||||||
|
void (*draw_func)(void *user_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct demo_swapchain
|
||||||
|
{
|
||||||
|
VkSurfaceKHR vk_surface;
|
||||||
|
VkSwapchainKHR vk_swapchain;
|
||||||
|
VkFence vk_fence;
|
||||||
|
|
||||||
|
VkInstance vk_instance;
|
||||||
|
VkDevice vk_device;
|
||||||
|
VkQueue vk_queue;
|
||||||
|
|
||||||
|
uint32_t current_buffer;
|
||||||
|
unsigned int buffer_count;
|
||||||
|
ID3D12Resource *buffers[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline xcb_atom_t demo_get_atom(xcb_connection_t *c, const char *name)
|
||||||
|
{
|
||||||
|
xcb_intern_atom_cookie_t cookie;
|
||||||
|
xcb_intern_atom_reply_t *reply;
|
||||||
|
xcb_atom_t atom = XCB_NONE;
|
||||||
|
|
||||||
|
cookie = xcb_intern_atom(c, 0, strlen(name), name);
|
||||||
|
if ((reply = xcb_intern_atom_reply(c, cookie, NULL)))
|
||||||
|
{
|
||||||
|
atom = reply->atom;
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool demo_add_window(struct demo *demo, struct demo_window *window)
|
||||||
|
{
|
||||||
|
if (demo->window_count == demo->windows_size)
|
||||||
|
{
|
||||||
|
size_t new_capacity;
|
||||||
|
void *new_elements;
|
||||||
|
|
||||||
|
new_capacity = max(demo->windows_size * 2, 4);
|
||||||
|
if (!(new_elements = realloc(demo->windows, new_capacity * sizeof(*demo->windows))))
|
||||||
|
return false;
|
||||||
|
demo->windows = new_elements;
|
||||||
|
demo->windows_size = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
demo->windows[demo->window_count++] = window;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_remove_window(struct demo *demo, const struct demo_window *window)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < demo->window_count; ++i)
|
||||||
|
{
|
||||||
|
if (demo->windows[i] != window)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
--demo->window_count;
|
||||||
|
memmove(&demo->windows[i], &demo->windows[i + 1], (demo->window_count - i) * sizeof(*demo->windows));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct demo_window *demo_find_window(struct demo *demo, xcb_window_t window)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < demo->window_count; ++i)
|
||||||
|
{
|
||||||
|
if (demo->windows[i]->window == window)
|
||||||
|
return demo->windows[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct demo_window *demo_window_create(struct demo *demo, const char *title,
|
||||||
|
unsigned int width, unsigned int height, void (*draw_func)(void *user_data), void *user_data)
|
||||||
|
{
|
||||||
|
static const uint32_t window_events = XCB_EVENT_MASK_EXPOSURE;
|
||||||
|
|
||||||
|
struct demo_window *window;
|
||||||
|
xcb_size_hints_t hints;
|
||||||
|
xcb_screen_t *screen;
|
||||||
|
|
||||||
|
if (!(window = malloc(sizeof(*window))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!demo_add_window(demo, window))
|
||||||
|
{
|
||||||
|
free(window);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->window = xcb_generate_id(demo->connection);
|
||||||
|
window->demo = demo;
|
||||||
|
window->draw_func = draw_func;
|
||||||
|
window->user_data = user_data;
|
||||||
|
screen = xcb_setup_roots_iterator(xcb_get_setup(demo->connection)).data;
|
||||||
|
xcb_create_window(demo->connection, XCB_COPY_FROM_PARENT, window->window, screen->root, 0, 0,
|
||||||
|
width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual,
|
||||||
|
XCB_CW_EVENT_MASK, &window_events);
|
||||||
|
xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME,
|
||||||
|
XCB_ATOM_STRING, 8, strlen(title), title);
|
||||||
|
xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, demo->wm_protocols_atom,
|
||||||
|
XCB_ATOM_ATOM, 32, 1, &demo->wm_delete_window_atom);
|
||||||
|
hints.flags = XCB_ICCCM_SIZE_HINT_P_MIN_SIZE | XCB_ICCCM_SIZE_HINT_P_MAX_SIZE;
|
||||||
|
hints.min_width = width;
|
||||||
|
hints.min_height = height;
|
||||||
|
hints.max_width = width;
|
||||||
|
hints.max_height = height;
|
||||||
|
xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NORMAL_HINTS,
|
||||||
|
XCB_ATOM_WM_SIZE_HINTS, 32, sizeof(hints) >> 2, &hints);
|
||||||
|
|
||||||
|
xcb_map_window(demo->connection, window->window);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_window_destroy(struct demo_window *window)
|
||||||
|
{
|
||||||
|
xcb_destroy_window(window->demo->connection, window->window);
|
||||||
|
xcb_flush(window->demo->connection);
|
||||||
|
demo_remove_window(window->demo, window);
|
||||||
|
free(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_process_events(struct demo *demo)
|
||||||
|
{
|
||||||
|
const xcb_client_message_event_t *client_message;
|
||||||
|
xcb_generic_event_t *event;
|
||||||
|
struct demo_window *window;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
xcb_flush(demo->connection);
|
||||||
|
|
||||||
|
while (!done && (event = xcb_wait_for_event(demo->connection)))
|
||||||
|
{
|
||||||
|
switch (XCB_EVENT_RESPONSE_TYPE(event))
|
||||||
|
{
|
||||||
|
case XCB_EXPOSE:
|
||||||
|
if ((window = demo_find_window(demo, ((struct xcb_expose_event_t *)event)->window)))
|
||||||
|
window->draw_func(window->user_data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCB_CLIENT_MESSAGE:
|
||||||
|
client_message = (xcb_client_message_event_t *)event;
|
||||||
|
if (client_message->type == demo->wm_protocols_atom
|
||||||
|
&& client_message->data.data32[0] == demo->wm_delete_window_atom
|
||||||
|
&& (window = demo_find_window(demo, client_message->window)))
|
||||||
|
{
|
||||||
|
demo_window_destroy(window);
|
||||||
|
if (!demo->window_count)
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool demo_init(struct demo *demo)
|
||||||
|
{
|
||||||
|
if (!(demo->connection = xcb_connect(NULL, NULL)))
|
||||||
|
return false;
|
||||||
|
if (xcb_connection_has_error(demo->connection) > 0)
|
||||||
|
goto fail;
|
||||||
|
if ((demo->wm_delete_window_atom = demo_get_atom(demo->connection, "WM_DELETE_WINDOW")) == XCB_NONE)
|
||||||
|
goto fail;
|
||||||
|
if ((demo->wm_protocols_atom = demo_get_atom(demo->connection, "WM_PROTOCOLS")) == XCB_NONE)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
demo->windows = NULL;
|
||||||
|
demo->windows_size = 0;
|
||||||
|
demo->window_count = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
xcb_disconnect(demo->connection);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_cleanup(struct demo *demo)
|
||||||
|
{
|
||||||
|
free(demo->windows);
|
||||||
|
xcb_disconnect(demo->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline DXGI_FORMAT demo_get_srgb_format(DXGI_FORMAT format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
|
default:
|
||||||
|
return DXGI_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *command_queue,
|
||||||
|
struct demo_window *window, const struct demo_swapchain_desc *desc)
|
||||||
|
{
|
||||||
|
struct VkSwapchainCreateInfoKHR vk_swapchain_desc;
|
||||||
|
struct VkXcbSurfaceCreateInfoKHR surface_desc;
|
||||||
|
VkSwapchainKHR vk_swapchain = VK_NULL_HANDLE;
|
||||||
|
uint32_t format_count, queue_family_index;
|
||||||
|
VkSurfaceCapabilitiesKHR surface_caps;
|
||||||
|
VkPhysicalDevice vk_physical_device;
|
||||||
|
D3D12_RESOURCE_DESC resource_desc;
|
||||||
|
VkFence vk_fence = VK_NULL_HANDLE;
|
||||||
|
struct demo_swapchain *swapchain;
|
||||||
|
unsigned int image_count, i, j;
|
||||||
|
VkFenceCreateInfo fence_desc;
|
||||||
|
VkSurfaceFormatKHR *formats;
|
||||||
|
ID3D12Device *d3d12_device;
|
||||||
|
VkSurfaceKHR vk_surface;
|
||||||
|
VkInstance vk_instance;
|
||||||
|
VkBool32 supported;
|
||||||
|
VkDevice vk_device;
|
||||||
|
VkImage *vk_images;
|
||||||
|
VkFormat format;
|
||||||
|
|
||||||
|
if ((format = vkd3d_get_vk_format(demo_get_srgb_format(desc->format))) == VK_FORMAT_UNDEFINED)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (FAILED(ID3D12CommandQueue_GetDevice(command_queue, &IID_ID3D12Device, (void **)&d3d12_device)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
vk_instance = vkd3d_get_vk_instance(d3d12_device);
|
||||||
|
vk_physical_device = vkd3d_get_vk_physical_device(d3d12_device);
|
||||||
|
vk_device = vkd3d_get_vk_device(d3d12_device);
|
||||||
|
|
||||||
|
surface_desc.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||||
|
surface_desc.pNext = NULL;
|
||||||
|
surface_desc.flags = 0;
|
||||||
|
surface_desc.connection = window->demo->connection;
|
||||||
|
surface_desc.window = window->window;
|
||||||
|
if (vkCreateXcbSurfaceKHR(vk_instance, &surface_desc, NULL, &vk_surface) < 0)
|
||||||
|
{
|
||||||
|
ID3D12Device_Release(d3d12_device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_family_index = vkd3d_get_vk_queue_family_index(command_queue);
|
||||||
|
if (vkGetPhysicalDeviceSurfaceSupportKHR(vk_physical_device,
|
||||||
|
queue_family_index, vk_surface, &supported) < 0 || !supported)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical_device, vk_surface, &surface_caps) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if ((surface_caps.maxImageCount && desc->buffer_count > surface_caps.maxImageCount)
|
||||||
|
|| desc->buffer_count < surface_caps.minImageCount
|
||||||
|
|| desc->width > surface_caps.maxImageExtent.width || desc->width < surface_caps.minImageExtent.width
|
||||||
|
|| desc->height > surface_caps.maxImageExtent.height || desc->height < surface_caps.minImageExtent.height
|
||||||
|
|| !(surface_caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, NULL) < 0
|
||||||
|
|| !format_count || !(formats = calloc(format_count, sizeof(*formats))))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physical_device, vk_surface, &format_count, formats) < 0)
|
||||||
|
{
|
||||||
|
free(formats);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format_count != 1 || formats->format != VK_FORMAT_UNDEFINED
|
||||||
|
|| formats->colorSpace != VK_COLORSPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
{
|
||||||
|
for (i = 0; i < format_count; ++i)
|
||||||
|
{
|
||||||
|
if (formats[i].format == format && formats[i].colorSpace == VK_COLORSPACE_SRGB_NONLINEAR_KHR)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == format_count)
|
||||||
|
{
|
||||||
|
free(formats);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(formats);
|
||||||
|
formats = NULL;
|
||||||
|
|
||||||
|
vk_swapchain_desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
vk_swapchain_desc.pNext = NULL;
|
||||||
|
vk_swapchain_desc.flags = 0;
|
||||||
|
vk_swapchain_desc.surface = vk_surface;
|
||||||
|
vk_swapchain_desc.minImageCount = desc->buffer_count;
|
||||||
|
vk_swapchain_desc.imageFormat = format;
|
||||||
|
vk_swapchain_desc.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
vk_swapchain_desc.imageExtent.width = desc->width;
|
||||||
|
vk_swapchain_desc.imageExtent.height = desc->height;
|
||||||
|
vk_swapchain_desc.imageArrayLayers = 1;
|
||||||
|
vk_swapchain_desc.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
vk_swapchain_desc.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
vk_swapchain_desc.queueFamilyIndexCount = 0;
|
||||||
|
vk_swapchain_desc.pQueueFamilyIndices = NULL;
|
||||||
|
vk_swapchain_desc.preTransform = surface_caps.currentTransform;
|
||||||
|
vk_swapchain_desc.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
vk_swapchain_desc.presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
vk_swapchain_desc.clipped = VK_TRUE;
|
||||||
|
vk_swapchain_desc.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
if (vkCreateSwapchainKHR(vk_device, &vk_swapchain_desc, NULL, &vk_swapchain) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
|
fence_desc.pNext = NULL;
|
||||||
|
fence_desc.flags = 0;
|
||||||
|
if (vkCreateFence(vk_device, &fence_desc, NULL, &vk_fence) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, NULL) < 0
|
||||||
|
|| !(vk_images = calloc(image_count, sizeof(*vk_images))))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (vkGetSwapchainImagesKHR(vk_device, vk_swapchain, &image_count, vk_images) < 0)
|
||||||
|
{
|
||||||
|
free(vk_images);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(swapchain = malloc(offsetof(struct demo_swapchain, buffers[image_count]))))
|
||||||
|
{
|
||||||
|
free(vk_images);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
swapchain->vk_surface = vk_surface;
|
||||||
|
swapchain->vk_swapchain = vk_swapchain;
|
||||||
|
swapchain->vk_fence = vk_fence;
|
||||||
|
swapchain->vk_instance = vk_instance;
|
||||||
|
swapchain->vk_device = vk_device;
|
||||||
|
swapchain->vk_queue = vkd3d_get_vk_queue(command_queue);
|
||||||
|
|
||||||
|
vkAcquireNextImageKHR(vk_device, vk_swapchain, UINT64_MAX,
|
||||||
|
VK_NULL_HANDLE, vk_fence, &swapchain->current_buffer);
|
||||||
|
vkWaitForFences(vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX);
|
||||||
|
vkResetFences(vk_device, 1, &vk_fence);
|
||||||
|
|
||||||
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||||
|
resource_desc.Alignment = 0;
|
||||||
|
resource_desc.Width = desc->width;
|
||||||
|
resource_desc.Height = desc->height;
|
||||||
|
resource_desc.DepthOrArraySize = 1;
|
||||||
|
resource_desc.MipLevels = 1;
|
||||||
|
resource_desc.Format = desc->format;
|
||||||
|
resource_desc.SampleDesc.Count = 1;
|
||||||
|
resource_desc.SampleDesc.Quality = 0;
|
||||||
|
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||||
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
|
for (i = 0; i < image_count; ++i)
|
||||||
|
{
|
||||||
|
if (FAILED(vkd3d_create_image_resource(d3d12_device,
|
||||||
|
&resource_desc, vk_images[i], &swapchain->buffers[i])))
|
||||||
|
{
|
||||||
|
for (j = 0; j < i; ++j)
|
||||||
|
{
|
||||||
|
ID3D12Resource_Release(swapchain->buffers[j]);
|
||||||
|
}
|
||||||
|
free(swapchain);
|
||||||
|
free(vk_images);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swapchain->buffer_count = image_count;
|
||||||
|
free(vk_images);
|
||||||
|
ID3D12Device_Release(d3d12_device);
|
||||||
|
|
||||||
|
return swapchain;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (vk_fence != VK_NULL_HANDLE)
|
||||||
|
vkDestroyFence(vk_device, vk_fence, NULL);
|
||||||
|
if (vk_swapchain != VK_NULL_HANDLE)
|
||||||
|
vkDestroySwapchainKHR(vk_device, vk_swapchain, NULL);
|
||||||
|
vkDestroySurfaceKHR(vk_instance, vk_surface, NULL);
|
||||||
|
ID3D12Device_Release(d3d12_device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int demo_swapchain_get_current_back_buffer_index(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
return swapchain->current_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ID3D12Resource *demo_swapchain_get_back_buffer(struct demo_swapchain *swapchain, unsigned int index)
|
||||||
|
{
|
||||||
|
ID3D12Resource *resource = NULL;
|
||||||
|
|
||||||
|
if (index < swapchain->buffer_count && (resource = swapchain->buffers[index]))
|
||||||
|
ID3D12Resource_AddRef(resource);
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_swapchain_present(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
VkPresentInfoKHR present_desc;
|
||||||
|
|
||||||
|
present_desc.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
present_desc.pNext = NULL;
|
||||||
|
present_desc.waitSemaphoreCount = 0;
|
||||||
|
present_desc.pWaitSemaphores = NULL;
|
||||||
|
present_desc.swapchainCount = 1;
|
||||||
|
present_desc.pSwapchains = &swapchain->vk_swapchain;
|
||||||
|
present_desc.pImageIndices = &swapchain->current_buffer;
|
||||||
|
present_desc.pResults = NULL;
|
||||||
|
|
||||||
|
vkQueuePresentKHR(swapchain->vk_queue, &present_desc);
|
||||||
|
|
||||||
|
vkAcquireNextImageKHR(swapchain->vk_device, swapchain->vk_swapchain, UINT64_MAX,
|
||||||
|
VK_NULL_HANDLE, swapchain->vk_fence, &swapchain->current_buffer);
|
||||||
|
vkWaitForFences(swapchain->vk_device, 1, &swapchain->vk_fence, VK_TRUE, UINT64_MAX);
|
||||||
|
vkResetFences(swapchain->vk_device, 1, &swapchain->vk_fence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < swapchain->buffer_count; ++i)
|
||||||
|
{
|
||||||
|
ID3D12Resource_Release(swapchain->buffers[i]);
|
||||||
|
}
|
||||||
|
vkDestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL);
|
||||||
|
vkDestroySwapchainKHR(swapchain->vk_device, swapchain->vk_swapchain, NULL);
|
||||||
|
vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL);
|
||||||
|
free(swapchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline HANDLE demo_create_event(void)
|
||||||
|
{
|
||||||
|
return vkd3d_create_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int demo_wait_event(HANDLE event, unsigned int ms)
|
||||||
|
{
|
||||||
|
return vkd3d_wait_event(event, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void demo_destroy_event(HANDLE event)
|
||||||
|
{
|
||||||
|
vkd3d_destroy_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline HRESULT demo_create_root_signature(ID3D12Device *device,
|
||||||
|
const D3D12_ROOT_SIGNATURE_DESC *desc, ID3D12RootSignature **signature)
|
||||||
|
{
|
||||||
|
return ID3D12Device_CreateRootSignature(device, 0, desc, ~(SIZE_T)0,
|
||||||
|
&IID_ID3D12RootSignature, (void **)signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool demo_load_shader(struct demo *demo, const wchar_t *hlsl_name, const char *entry_point,
|
||||||
|
const char *profile, const char *spv_name, D3D12_SHADER_BYTECODE *shader)
|
||||||
|
{
|
||||||
|
size_t data_size;
|
||||||
|
struct stat st;
|
||||||
|
ssize_t res;
|
||||||
|
void *data;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if ((fd = open(spv_name, O_RDONLY)) == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fstat(fd, &st) == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
data_size = st.st_size;
|
||||||
|
if (!(data = malloc(data_size)))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
res = read(fd, data, data_size);
|
||||||
|
close(fd);
|
||||||
|
if (res != data_size)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->pShaderBytecode = data;
|
||||||
|
shader->BytecodeLength = data_size;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
410
demos/triangle.c
Normal file
410
demos/triangle.c
Normal file
@ -0,0 +1,410 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Henri Verbeet for CodeWeavers
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This application contains code derived from Microsoft's "HelloTriangle"
|
||||||
|
* demo, the license for which follows:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Microsoft
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INITGUID
|
||||||
|
#include <limits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "demo.h"
|
||||||
|
|
||||||
|
struct cxt_fence
|
||||||
|
{
|
||||||
|
ID3D12Fence *fence;
|
||||||
|
UINT64 value;
|
||||||
|
HANDLE event;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cx_triangle
|
||||||
|
{
|
||||||
|
struct demo demo;
|
||||||
|
|
||||||
|
struct demo_window *window;
|
||||||
|
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
float aspect_ratio;
|
||||||
|
|
||||||
|
D3D12_VIEWPORT vp;
|
||||||
|
D3D12_RECT scissor_rect;
|
||||||
|
|
||||||
|
ID3D12Device *device;
|
||||||
|
ID3D12CommandQueue *command_queue;
|
||||||
|
struct demo_swapchain *swapchain;
|
||||||
|
ID3D12DescriptorHeap *rtv_heap;
|
||||||
|
unsigned int rtv_descriptor_size;
|
||||||
|
ID3D12Resource *render_targets[2];
|
||||||
|
ID3D12CommandAllocator *command_allocator;
|
||||||
|
|
||||||
|
ID3D12RootSignature *root_signature;
|
||||||
|
ID3D12PipelineState *pipeline_state;
|
||||||
|
ID3D12GraphicsCommandList *command_list;
|
||||||
|
ID3D12Resource *vb;
|
||||||
|
D3D12_VERTEX_BUFFER_VIEW vbv;
|
||||||
|
|
||||||
|
unsigned int frame_idx;
|
||||||
|
struct cxt_fence fence;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void cxt_populate_command_list(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
static const float clear_colour[] = {0.0f, 0.2f, 0.4f, 1.0f};
|
||||||
|
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle;
|
||||||
|
D3D12_RESOURCE_BARRIER barrier;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = ID3D12CommandAllocator_Reset(cxt->command_allocator);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
hr = ID3D12GraphicsCommandList_Reset(cxt->command_list, cxt->command_allocator, cxt->pipeline_state);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList_SetGraphicsRootSignature(cxt->command_list, cxt->root_signature);
|
||||||
|
ID3D12GraphicsCommandList_RSSetViewports(cxt->command_list, 1, &cxt->vp);
|
||||||
|
ID3D12GraphicsCommandList_RSSetScissorRects(cxt->command_list, 1, &cxt->scissor_rect);
|
||||||
|
|
||||||
|
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||||
|
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||||
|
barrier.Transition.pResource = cxt->render_targets[cxt->frame_idx];
|
||||||
|
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||||
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||||
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||||
|
ID3D12GraphicsCommandList_ResourceBarrier(cxt->command_list, 1, &barrier);
|
||||||
|
|
||||||
|
rtv_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cxt->rtv_heap);
|
||||||
|
rtv_handle.ptr += cxt->frame_idx * cxt->rtv_descriptor_size;
|
||||||
|
ID3D12GraphicsCommandList_OMSetRenderTargets(cxt->command_list, 1, &rtv_handle, FALSE, NULL);
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList_ClearRenderTargetView(cxt->command_list, rtv_handle, clear_colour, 0, NULL);
|
||||||
|
ID3D12GraphicsCommandList_IASetPrimitiveTopology(cxt->command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
ID3D12GraphicsCommandList_IASetVertexBuffers(cxt->command_list, 0, 1, &cxt->vbv);
|
||||||
|
ID3D12GraphicsCommandList_DrawInstanced(cxt->command_list, 3, 1, 0, 0);
|
||||||
|
|
||||||
|
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||||
|
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||||
|
ID3D12GraphicsCommandList_ResourceBarrier(cxt->command_list, 1, &barrier);
|
||||||
|
|
||||||
|
hr = ID3D12GraphicsCommandList_Close(cxt->command_list);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_wait_for_previous_frame(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
struct cxt_fence *fence = &cxt->fence;
|
||||||
|
const UINT64 v = fence->value;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = ID3D12CommandQueue_Signal(cxt->command_queue, fence->fence, v);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
++fence->value;
|
||||||
|
|
||||||
|
if (ID3D12Fence_GetCompletedValue(fence->fence) < v)
|
||||||
|
{
|
||||||
|
ID3D12Fence_SetEventOnCompletion(fence->fence, v, fence->event);
|
||||||
|
demo_wait_event(fence->event, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cxt->frame_idx = demo_swapchain_get_current_back_buffer_index(cxt->swapchain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_render_frame(void *user_data)
|
||||||
|
{
|
||||||
|
struct cx_triangle *cxt = user_data;
|
||||||
|
|
||||||
|
cxt_populate_command_list(cxt);
|
||||||
|
ID3D12CommandQueue_ExecuteCommandLists(cxt->command_queue, 1, (ID3D12CommandList **)&cxt->command_list);
|
||||||
|
demo_swapchain_present(cxt->swapchain);
|
||||||
|
cxt_wait_for_previous_frame(cxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_destroy_pipeline(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
ID3D12CommandAllocator_Release(cxt->command_allocator);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cxt->render_targets); ++i)
|
||||||
|
{
|
||||||
|
ID3D12Resource_Release(cxt->render_targets[i]);
|
||||||
|
}
|
||||||
|
ID3D12DescriptorHeap_Release(cxt->rtv_heap);
|
||||||
|
demo_swapchain_destroy(cxt->swapchain);
|
||||||
|
ID3D12CommandQueue_Release(cxt->command_queue);
|
||||||
|
ID3D12Device_Release(cxt->device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_load_pipeline(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
struct demo_swapchain_desc swapchain_desc;
|
||||||
|
D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc;
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle;
|
||||||
|
D3D12_COMMAND_QUEUE_DESC queue_desc;
|
||||||
|
unsigned int i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&cxt->device);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
memset(&queue_desc, 0, sizeof(queue_desc));
|
||||||
|
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
|
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
|
hr = ID3D12Device_CreateCommandQueue(cxt->device, &queue_desc,
|
||||||
|
&IID_ID3D12CommandQueue, (void **)&cxt->command_queue);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
swapchain_desc.buffer_count = ARRAY_SIZE(cxt->render_targets);
|
||||||
|
swapchain_desc.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
swapchain_desc.width = cxt->width;
|
||||||
|
swapchain_desc.height = cxt->height;
|
||||||
|
cxt->swapchain = demo_swapchain_create(cxt->command_queue, cxt->window, &swapchain_desc);
|
||||||
|
assert(cxt->swapchain);
|
||||||
|
cxt->frame_idx = demo_swapchain_get_current_back_buffer_index(cxt->swapchain);
|
||||||
|
|
||||||
|
memset(&rtv_heap_desc, 0, sizeof(rtv_heap_desc));
|
||||||
|
rtv_heap_desc.NumDescriptors = ARRAY_SIZE(cxt->render_targets);
|
||||||
|
rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||||
|
rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||||
|
hr = ID3D12Device_CreateDescriptorHeap(cxt->device, &rtv_heap_desc,
|
||||||
|
&IID_ID3D12DescriptorHeap, (void **)&cxt->rtv_heap);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
cxt->rtv_descriptor_size = ID3D12Device_GetDescriptorHandleIncrementSize(cxt->device,
|
||||||
|
D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||||
|
rtv_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(cxt->rtv_heap);
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cxt->render_targets); ++i)
|
||||||
|
{
|
||||||
|
cxt->render_targets[i] = demo_swapchain_get_back_buffer(cxt->swapchain, i);
|
||||||
|
ID3D12Device_CreateRenderTargetView(cxt->device, cxt->render_targets[i], NULL, rtv_handle);
|
||||||
|
rtv_handle.ptr += cxt->rtv_descriptor_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommandAllocator(cxt->device, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||||
|
&IID_ID3D12CommandAllocator, (void **)&cxt->command_allocator);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_fence_destroy(struct cxt_fence *cxt_fence)
|
||||||
|
{
|
||||||
|
ID3D12Fence_Release(cxt_fence->fence);
|
||||||
|
demo_destroy_event(cxt_fence->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_destroy_assets(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
cxt_fence_destroy(&cxt->fence);
|
||||||
|
ID3D12Resource_Release(cxt->vb);
|
||||||
|
ID3D12GraphicsCommandList_Release(cxt->command_list);
|
||||||
|
ID3D12PipelineState_Release(cxt->pipeline_state);
|
||||||
|
ID3D12RootSignature_Release(cxt->root_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_load_shaders(struct cx_triangle *cxt, D3D12_SHADER_BYTECODE *vs, D3D12_SHADER_BYTECODE *ps)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
ret = demo_load_shader(&cxt->demo, L"triangle.hlsl", "vs_main", "vs_5_0", "triangle.vert.spv", vs);
|
||||||
|
assert(ret);
|
||||||
|
ret = demo_load_shader(&cxt->demo, L"triangle.hlsl", "ps_main", "ps_5_0", "triangle.frag.spv", ps);
|
||||||
|
assert(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_fence_create(struct cxt_fence *fence, ID3D12Device *device)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
|
||||||
|
&IID_ID3D12Fence, (void **)&fence->fence);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
fence->value = 1;
|
||||||
|
fence->event = demo_create_event();
|
||||||
|
assert(fence->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cxt_load_assets(struct cx_triangle *cxt)
|
||||||
|
{
|
||||||
|
static const D3D12_INPUT_ELEMENT_DESC il_desc[] =
|
||||||
|
{
|
||||||
|
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||||
|
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct
|
||||||
|
{
|
||||||
|
struct demo_vec3 position;
|
||||||
|
struct demo_vec4 colour;
|
||||||
|
}
|
||||||
|
vertices[] =
|
||||||
|
{
|
||||||
|
{{ 0.0f, 0.25f * cxt->aspect_ratio, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}},
|
||||||
|
{{ 0.25f, -0.25f * cxt->aspect_ratio, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}},
|
||||||
|
{{-0.25f, -0.25f * cxt->aspect_ratio, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}},
|
||||||
|
};
|
||||||
|
|
||||||
|
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
|
||||||
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc;
|
||||||
|
D3D12_RESOURCE_DESC resource_desc;
|
||||||
|
D3D12_HEAP_PROPERTIES heap_desc;
|
||||||
|
D3D12_RANGE read_range = {0, 0};
|
||||||
|
HRESULT hr;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
memset(&root_signature_desc, 0, sizeof(root_signature_desc));
|
||||||
|
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||||
|
hr = demo_create_root_signature(cxt->device, &root_signature_desc, &cxt->root_signature);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
memset(&pso_desc, 0, sizeof(pso_desc));
|
||||||
|
pso_desc.InputLayout.pInputElementDescs = il_desc;
|
||||||
|
pso_desc.InputLayout.NumElements = ARRAY_SIZE(il_desc);
|
||||||
|
pso_desc.pRootSignature = cxt->root_signature;
|
||||||
|
cxt_load_shaders(cxt, &pso_desc.VS, &pso_desc.PS);
|
||||||
|
demo_rasterizer_desc_init_default(&pso_desc.RasterizerState);
|
||||||
|
demo_blend_desc_init_default(&pso_desc.BlendState);
|
||||||
|
pso_desc.DepthStencilState.DepthEnable = FALSE;
|
||||||
|
pso_desc.DepthStencilState.StencilEnable = FALSE;
|
||||||
|
pso_desc.SampleMask = UINT_MAX;
|
||||||
|
pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||||
|
pso_desc.NumRenderTargets = 1;
|
||||||
|
pso_desc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
pso_desc.SampleDesc.Count = 1;
|
||||||
|
hr = ID3D12Device_CreateGraphicsPipelineState(cxt->device, &pso_desc,
|
||||||
|
&IID_ID3D12PipelineState, (void **)&cxt->pipeline_state);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
free((void *)pso_desc.PS.pShaderBytecode);
|
||||||
|
free((void *)pso_desc.VS.pShaderBytecode);
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommandList(cxt->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, cxt->command_allocator,
|
||||||
|
cxt->pipeline_state, &IID_ID3D12GraphicsCommandList, (void **)&cxt->command_list);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
hr = ID3D12GraphicsCommandList_Close(cxt->command_list);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
heap_desc.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
|
heap_desc.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
|
heap_desc.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
|
heap_desc.CreationNodeMask = 1;
|
||||||
|
heap_desc.VisibleNodeMask = 1;
|
||||||
|
|
||||||
|
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||||
|
resource_desc.Alignment = 0;
|
||||||
|
resource_desc.Width = sizeof(vertices);
|
||||||
|
resource_desc.Height = 1;
|
||||||
|
resource_desc.DepthOrArraySize = 1;
|
||||||
|
resource_desc.MipLevels = 1;
|
||||||
|
resource_desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
|
resource_desc.SampleDesc.Count = 1;
|
||||||
|
resource_desc.SampleDesc.Quality = 0;
|
||||||
|
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||||
|
resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
hr = ID3D12Device_CreateCommittedResource(cxt->device, &heap_desc, D3D12_HEAP_FLAG_NONE, &resource_desc,
|
||||||
|
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &IID_ID3D12Resource, (void **)&cxt->vb);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
|
hr = ID3D12Resource_Map(cxt->vb, 0, &read_range, &data);
|
||||||
|
assert(SUCCEEDED(hr));
|
||||||
|
memcpy(data, vertices, sizeof(vertices));
|
||||||
|
ID3D12Resource_Unmap(cxt->vb, 0, NULL);
|
||||||
|
|
||||||
|
cxt->vbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(cxt->vb);
|
||||||
|
cxt->vbv.StrideInBytes = sizeof(*vertices);
|
||||||
|
cxt->vbv.SizeInBytes = sizeof(vertices);
|
||||||
|
|
||||||
|
cxt_fence_create(&cxt->fence, cxt->device);
|
||||||
|
cxt_wait_for_previous_frame(cxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cxt_main(void)
|
||||||
|
{
|
||||||
|
unsigned int width = 640, height = 480;
|
||||||
|
struct cx_triangle cxt;
|
||||||
|
|
||||||
|
memset(&cxt, 0, sizeof(cxt));
|
||||||
|
|
||||||
|
if (!demo_init(&cxt.demo))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
cxt.window = demo_window_create(&cxt.demo, "Vkd3d Triangle",
|
||||||
|
width, height, cxt_render_frame, &cxt);
|
||||||
|
|
||||||
|
cxt.width = width;
|
||||||
|
cxt.height = height;
|
||||||
|
cxt.aspect_ratio = (float)width / (float)height;
|
||||||
|
|
||||||
|
cxt.vp.Width = (float)width;
|
||||||
|
cxt.vp.Height = (float)height;
|
||||||
|
cxt.vp.MaxDepth = 1.0f;
|
||||||
|
|
||||||
|
cxt.scissor_rect.right = width;
|
||||||
|
cxt.scissor_rect.bottom = height;
|
||||||
|
|
||||||
|
cxt_load_pipeline(&cxt);
|
||||||
|
cxt_load_assets(&cxt);
|
||||||
|
|
||||||
|
demo_process_events(&cxt.demo);
|
||||||
|
|
||||||
|
cxt_wait_for_previous_frame(&cxt);
|
||||||
|
cxt_destroy_assets(&cxt);
|
||||||
|
cxt_destroy_pipeline(&cxt);
|
||||||
|
demo_cleanup(&cxt.demo);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int wmain(void)
|
||||||
|
#else
|
||||||
|
int main(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return cxt_main();
|
||||||
|
}
|
10
demos/triangle.frag
Normal file
10
demos/triangle.frag
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 150
|
||||||
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 colour_in;
|
||||||
|
layout(location = 0) out vec4 colour_out;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
colour_out = colour_in;
|
||||||
|
}
|
20
demos/triangle.hlsl
Normal file
20
demos/triangle.hlsl
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
struct ps_in
|
||||||
|
{
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float4 colour : COLOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ps_in vs_main(float4 position : POSITION, float4 colour : COLOR)
|
||||||
|
{
|
||||||
|
struct ps_in o;
|
||||||
|
|
||||||
|
o.position = position;
|
||||||
|
o.colour = colour;
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 ps_main(struct ps_in i) : SV_TARGET
|
||||||
|
{
|
||||||
|
return i.colour;
|
||||||
|
}
|
14
demos/triangle.vert
Normal file
14
demos/triangle.vert
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 150
|
||||||
|
#extension GL_ARB_separate_shader_objects : enable
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 position_in;
|
||||||
|
layout(location = 1) in vec4 colour_in;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 colour_out;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position.xzw = position_in.xzw;
|
||||||
|
gl_Position.y = -position_in.y;
|
||||||
|
colour_out = colour_in;
|
||||||
|
}
|
@ -25,6 +25,14 @@ import "dxgitype.idl";
|
|||||||
|
|
||||||
#include "unknown.idl"
|
#include "unknown.idl"
|
||||||
|
|
||||||
|
typedef enum DXGI_SWAP_EFFECT
|
||||||
|
{
|
||||||
|
DXGI_SWAP_EFFECT_DISCARD = 0x0,
|
||||||
|
DXGI_SWAP_EFFECT_SEQUENTIAL = 0x1,
|
||||||
|
DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL = 0x3,
|
||||||
|
DXGI_SWAP_EFFECT_FLIP_DISCARD = 0x4,
|
||||||
|
} DXGI_SWAP_EFFECT;
|
||||||
|
|
||||||
typedef enum DXGI_MODE_ROTATION
|
typedef enum DXGI_MODE_ROTATION
|
||||||
{
|
{
|
||||||
DXGI_MODE_ROTATION_UNSPECIFIED = 0x0,
|
DXGI_MODE_ROTATION_UNSPECIFIED = 0x0,
|
||||||
@ -40,6 +48,16 @@ interface IDXGIOutput;
|
|||||||
typedef struct DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC;
|
typedef struct DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC;
|
||||||
typedef struct DXGI_FRAME_STATISTICS DXGI_FRAME_STATISTICS;
|
typedef struct DXGI_FRAME_STATISTICS DXGI_FRAME_STATISTICS;
|
||||||
|
|
||||||
|
typedef UINT DXGI_USAGE;
|
||||||
|
|
||||||
|
const DXGI_USAGE DXGI_USAGE_SHADER_INPUT = 0x00000010ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_RENDER_TARGET_OUTPUT = 0x00000020ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_BACK_BUFFER = 0x00000040ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_SHARED = 0x00000080ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_READ_ONLY = 0x00000100ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_DISCARD_ON_PRESENT = 0x00000200ul;
|
||||||
|
const DXGI_USAGE DXGI_USAGE_UNORDERED_ACCESS = 0x00000400ul;
|
||||||
|
|
||||||
[
|
[
|
||||||
local,
|
local,
|
||||||
object,
|
object,
|
||||||
|
@ -23,7 +23,38 @@
|
|||||||
|
|
||||||
import "dxgi.idl";
|
import "dxgi.idl";
|
||||||
|
|
||||||
typedef struct DXGI_SWAP_CHAIN_DESC1 DXGI_SWAP_CHAIN_DESC1;
|
typedef enum DXGI_SCALING
|
||||||
|
{
|
||||||
|
DXGI_SCALING_STRETCH = 0x0,
|
||||||
|
DXGI_SCALING_NONE = 0x1,
|
||||||
|
DXGI_SCALING_ASPECT_RATIO_STRETCH = 0x2,
|
||||||
|
DXGI_SCALING_FORCE_DWORD = 0xffffffff,
|
||||||
|
} DXGI_SCALING;
|
||||||
|
|
||||||
|
typedef enum DXGI_ALPHA_MODE
|
||||||
|
{
|
||||||
|
DXGI_ALPHA_MODE_UNSPECIFIED = 0x0,
|
||||||
|
DXGI_ALPHA_MODE_PREMULTIPLIED = 0x1,
|
||||||
|
DXGI_ALPHA_MODE_STRAIGHT = 0x2,
|
||||||
|
DXGI_ALPHA_MODE_IGNORE = 0x3,
|
||||||
|
DXGI_ALPHA_MODE_FORCE_DWORD = 0xffffffff,
|
||||||
|
} DXGI_ALPHA_MODE;
|
||||||
|
|
||||||
|
typedef struct DXGI_SWAP_CHAIN_DESC1
|
||||||
|
{
|
||||||
|
UINT Width;
|
||||||
|
UINT Height;
|
||||||
|
DXGI_FORMAT Format;
|
||||||
|
BOOL Stereo;
|
||||||
|
DXGI_SAMPLE_DESC SampleDesc;
|
||||||
|
DXGI_USAGE BufferUsage;
|
||||||
|
UINT BufferCount;
|
||||||
|
DXGI_SCALING Scaling;
|
||||||
|
DXGI_SWAP_EFFECT SwapEffect;
|
||||||
|
DXGI_ALPHA_MODE AlphaMode;
|
||||||
|
UINT Flags;
|
||||||
|
} DXGI_SWAP_CHAIN_DESC1;
|
||||||
|
|
||||||
typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
|
typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
|
||||||
typedef struct DXGI_PRESENT_PARAMETERS DXGI_PRESENT_PARAMETERS;
|
typedef struct DXGI_PRESENT_PARAMETERS DXGI_PRESENT_PARAMETERS;
|
||||||
|
|
||||||
|
@ -24,6 +24,12 @@
|
|||||||
|
|
||||||
static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance)
|
static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance)
|
||||||
{
|
{
|
||||||
|
static const char * const extensions[] =
|
||||||
|
{
|
||||||
|
"VK_KHR_surface",
|
||||||
|
"VK_KHR_xcb_surface",
|
||||||
|
};
|
||||||
|
|
||||||
VkApplicationInfo application_info;
|
VkApplicationInfo application_info;
|
||||||
VkInstanceCreateInfo instance_info;
|
VkInstanceCreateInfo instance_info;
|
||||||
VkInstance vk_instance;
|
VkInstance vk_instance;
|
||||||
@ -46,8 +52,8 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance)
|
|||||||
instance_info.pApplicationInfo = &application_info;
|
instance_info.pApplicationInfo = &application_info;
|
||||||
instance_info.enabledLayerCount = 0;
|
instance_info.enabledLayerCount = 0;
|
||||||
instance_info.ppEnabledLayerNames = NULL;
|
instance_info.ppEnabledLayerNames = NULL;
|
||||||
instance_info.enabledExtensionCount = 0;
|
instance_info.enabledExtensionCount = ARRAY_SIZE(extensions);
|
||||||
instance_info.ppEnabledExtensionNames = NULL;
|
instance_info.ppEnabledExtensionNames = extensions;
|
||||||
|
|
||||||
if ((vr = vkCreateInstance(&instance_info, NULL, &vk_instance)))
|
if ((vr = vkCreateInstance(&instance_info, NULL, &vk_instance)))
|
||||||
{
|
{
|
||||||
@ -351,6 +357,11 @@ static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance,
|
|||||||
|
|
||||||
static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
|
static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
|
||||||
{
|
{
|
||||||
|
static const char * const extensions[] =
|
||||||
|
{
|
||||||
|
"VK_KHR_swapchain",
|
||||||
|
};
|
||||||
|
|
||||||
const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance.vk_procs;
|
const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance.vk_procs;
|
||||||
unsigned int direct_queue_family_index, copy_queue_family_index;
|
unsigned int direct_queue_family_index, copy_queue_family_index;
|
||||||
VkQueueFamilyProperties *queue_properties;
|
VkQueueFamilyProperties *queue_properties;
|
||||||
@ -434,8 +445,8 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device)
|
|||||||
device_info.pQueueCreateInfos = queue_info;
|
device_info.pQueueCreateInfos = queue_info;
|
||||||
device_info.enabledLayerCount = 0;
|
device_info.enabledLayerCount = 0;
|
||||||
device_info.ppEnabledLayerNames = NULL;
|
device_info.ppEnabledLayerNames = NULL;
|
||||||
device_info.enabledExtensionCount = 0;
|
device_info.enabledExtensionCount = ARRAY_SIZE(extensions);
|
||||||
device_info.ppEnabledExtensionNames = NULL;
|
device_info.ppEnabledExtensionNames = extensions;
|
||||||
device_info.pEnabledFeatures = &device_features;
|
device_info.pEnabledFeatures = &device_features;
|
||||||
|
|
||||||
vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device));
|
vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device));
|
||||||
|
Loading…
Reference in New Issue
Block a user