initial import

This commit is contained in:
Danny Robson 2016-02-24 11:11:41 +11:00
commit 3229e63406
52 changed files with 6661 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/aclocal.m4
/autom4te.cache/
/build-aux/
/configure
*.in
/m4/libtool.m4
/m4/lt*.m4

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Danny Robson <danny@nerdcruft.net>

58
Makefile.am Normal file
View File

@ -0,0 +1,58 @@
AUTOMAKE_OPTIONS = dist-bzip2 dist-xz subdir-objects
ACLOCAL_AMFLAGS = -I m4
AM_CXXFLAGS = $(UTIL_CRUFT_CFLAGS)
DEFAULT_INCLUDES = -I${top_srcdir} -I${top_builddir} -I${top_builddir}/vk
noinst_LIBRARIES = libcruft-vk.a
SUFFIXES = .hpp.xml .hpp
vk.hpp: vk.xml vk.xsl
$(XSLTPROC) $(XSLTFLAGS) -o $(builddir)/$@ $(srcdir)/vk.xsl $(srcdir)/vk.xml
EXTRA_DIST = vk.xml vk.xsl
#BUILT_SOURCES = vk.hpp
libcruft_vk_a_SOURCES = \
vk.hpp \
fwd.hpp \
object.cpp \
object.hpp \
buffer.cpp \
buffer.hpp \
command_buffer.cpp \
command_buffer.hpp \
command_pool.cpp \
command_pool.hpp \
device.cpp \
device.hpp \
device_memory.cpp \
device_memory.hpp \
event.cpp \
event.hpp \
except.cpp \
except.hpp \
fence.cpp \
fence.hpp \
framebuffer.cpp \
framebuffer.hpp \
instance.cpp \
instance.hpp \
image.cpp \
image.hpp \
physical_device.cpp \
physical_device.hpp \
pipeline.cpp \
pipeline.hpp \
pipeline_cache.cpp \
pipeline_cache.hpp \
queue.cpp \
queue.hpp \
render_pass.cpp \
render_pass.hpp \
semaphore.cpp \
semaphore.hpp \
shader_module.cpp \
shader_module.hpp \
traits.hpp

7
buffer.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "./buffer.hpp"
using vk::buffer;
///////////////////////////////////////////////////////////////////////////////

13
buffer.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef __VK_BUFFER_HPP
#define __VK_BUFFER_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct buffer : public owned<buffer,device> {
};
}
#endif

108
command_buffer.cpp Normal file
View File

@ -0,0 +1,108 @@
#include "./command_buffer.hpp"
#include "./event.hpp"
#include "./pipeline.hpp"
using vk::command_buffer;
///////////////////////////////////////////////////////////////////////////////
void
command_buffer::reset (VkCommandBufferResetFlags flags)
{
auto err = vkResetCommandBuffer (id (), flags);
error::try_code (err);
}
///////////////////////////////////////////////////////////////////////////////
void
command_buffer::begin (const VkCommandBufferBeginInfo &info)
{
auto err = vkBeginCommandBuffer (id (), &info);
error::try_code (err);
}
//-----------------------------------------------------------------------------
void
command_buffer::begin (const VkRenderPassBeginInfo &info, VkSubpassContents contents)
{
vkCmdBeginRenderPass (id (), &info, contents);
}
//-----------------------------------------------------------------------------
void
command_buffer::end (void)
{
auto err = vkEndCommandBuffer (id ());
error::try_code (err);
}
//-----------------------------------------------------------------------------
void
command_buffer::end_pass (void)
{
vkCmdEndRenderPass (id ());
}
///////////////////////////////////////////////////////////////////////////////
template <size_t N>
void
command_buffer::execute (const command_buffer (&buffers)[N])
{
vkCmdExecuteCOmmands (id (), N, buffers);
}
//-----------------------------------------------------------------------------
void
command_buffer::next_subpass (const VkSubpassContents contents)
{
vkCmdNextSubpass (id (), contents);
}
///////////////////////////////////////////////////////////////////////////////
void
command_buffer::bind (VkPipelineBindPoint point, const pipeline &p)
{
vkCmdBindPipeline (id (), point, p.id ());
}
///////////////////////////////////////////////////////////////////////////////
void
command_buffer::set (const event &ev, VkPipelineStageFlags flags)
{
vkCmdSetEvent (id (), ev.id (), flags);
}
//-----------------------------------------------------------------------------
void
command_buffer::reset (const event &ev, VkPipelineStageFlags flags)
{
vkCmdResetEvent (id (), ev.id (), flags);
}
//-----------------------------------------------------------------------------
void
command_buffer::wait (util::view<const event*> events,
VkPipelineStageFlags src_mask,
VkPipelineStageFlags dst_mask,
util::view<const VkMemoryBarrier*> VkMemoryBarriers,
util::view<const VkBufferMemoryBarrier*> VkBufferMemoryBarriers,
util::view<const VkImageMemoryBarrier*> VkImageMemoryBarriers)
{
vkCmdWaitEvents (id (),
events.size (), &events.cbegin ()->id (),
src_mask, dst_mask,
VkMemoryBarriers.size (), VkMemoryBarriers.cbegin (),
VkBufferMemoryBarriers.size (), VkBufferMemoryBarriers.cbegin (),
VkImageMemoryBarriers.size (), VkImageMemoryBarriers.cbegin ());
}

44
command_buffer.hpp Normal file
View File

@ -0,0 +1,44 @@
#ifndef __VK_COMMAND_BUFFER_HPP
#define __VK_COMMAND_BUFFER_HPP
#include "./object.hpp"
#include <cruft/util/view.hpp>
namespace vk {
struct command_buffer : public owned<command_buffer,device> {
void reset (VkCommandBufferResetFlags);
void begin (const VkCommandBufferBeginInfo&);
void begin (const VkRenderPassBeginInfo&, VkSubpassContents);
void end (void);
void end_pass (void);
template <size_t N>
void execute (const command_buffer (&buffers)[N]);
void next_subpass (VkSubpassContents);
void bind (VkPipelineBindPoint, const pipeline&);
void set (const event&, VkPipelineStageFlags);
void reset (const event&, VkPipelineStageFlags);
void wait (util::view<const event*>,
VkPipelineStageFlags src_mask,
VkPipelineStageFlags dst_mask,
util::view<const VkMemoryBarrier*>,
util::view<const VkBufferMemoryBarrier*>,
util::view<const VkImageMemoryBarrier*>);
void pipeline_barrier (
VkPipelineStageFlags src_mask,
VkPipelineStageFlags dst_mask,
VkDependencyFlags,
util::view<const VkMemoryBarrier*>,
util::view<const VkBufferMemoryBarrier*>,
util::view<const VkImageMemoryBarrier*>);
};
}
#endif

14
command_pool.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "./command_pool.hpp"
#include "./device.hpp"
using vk::command_pool;
///////////////////////////////////////////////////////////////////////////////
void
command_pool::reset (const device &dev, VkCommandPoolResetFlags flags)
{
auto err = vkResetCommandPool (dev.id (), id (), flags);
error::try_code (err);
}

12
command_pool.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef __VK_COMMAND_POOL_HPP
#define __VK_COMMAND_POOL_HPP
#include "./object.hpp"
namespace vk {
struct command_pool : public owned<command_pool,device> {
void reset (const device&, VkCommandPoolResetFlags);
};
}
#endif

57
configure.ac Normal file
View File

@ -0,0 +1,57 @@
AC_INIT([vk-cruft], [0.0.1], [danny@nerdcruft.net], [], [http://nerdcruft.net/])
## Explicitly set an empty CXXFLAGS if not present to prevent AC_PROG_CXX from
## generating a default -O2. This allows us to manually select -O0 when
## debugging is enabled.
: ${CXXFLAGS=""}
###############################################################################
## Build environment discovery
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_USE_SYSTEM_EXTENSIONS
AC_CANONICAL_HOST
AC_LANG([C++])
NC_CXX
NC_PLATFORM
NC_OPTIMISATION
NC_WARNINGS
NC_DEBUGGING
LT_INIT
AM_INIT_AUTOMAKE([1.14 foreign dist-xz dist-bzip2 subdir-objects])
AM_SILENT_RULES([yes])
AC_CONFIG_HEADERS([config.h])
AX_CHECK_GNU_MAKE
###############################################################################
## Required build packages
AC_CHECK_PROGS([XSLTPROC], [xsltproc], [false])
AS_IF([test "x$XSLTPROC" == "xfalse"], [
AC_MSG_ERROR([Cannot find xsltproc])
])
###############################################################################
## Required packages
PKG_CHECK_MODULES([UTIL_CRUFT], [libcruft-util >= 0])
AC_SUBST([UTIL_CRUFT_CFLAGS])
AC_SUBST([UTIL_CRUFT_LIBS])
###############################################################################
## Output
AX_APPEND_FLAG([-include config.h])
AC_CONFIG_FILES([libcruft-vk.pc Makefile])
AC_OUTPUT

43
device.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "./device.hpp"
#include "./physical_device.hpp"
using vk::device;
///////////////////////////////////////////////////////////////////////////////
device::device (const physical_device &phys,
const VkDeviceCreateInfo &info):
instantiated (phys.id (), &info, nullptr)
{ ; }
///////////////////////////////////////////////////////////////////////////////
VkPhysicalDeviceMemoryProperties
device::physical_properties (void) const
{
VkPhysicalDeviceMemoryProperties props;
vkGetPhysicalDeviceMemoryProperties (id (), &props);
return props;
}
///////////////////////////////////////////////////////////////////////////////
void
device::flush (const VkMappedMemoryRange *first,
const VkMappedMemoryRange *last)
{
auto err = vkFlushMappedMemoryRanges (id (), last - first, first);
error::try_code (err);
}
//-----------------------------------------------------------------------------
void
device::invalidate (const VkMappedMemoryRange *first,
const VkMappedMemoryRange *last)
{
auto err = vkInvalidateMappedMemoryRanges (id (), last - first, first);
error::try_code (err);
}

24
device.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef __VK_DEVICE_HPP
#define __VK_DEVICE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct device : public instantiated<device> {
device (const physical_device&,
const VkDeviceCreateInfo&);
VkPhysicalDeviceMemoryProperties
physical_properties (void) const;
void flush (const VkMappedMemoryRange *first,
const VkMappedMemoryRange *last);
void invalidate (const VkMappedMemoryRange *first,
const VkMappedMemoryRange *last);
};
}
#endif

39
device_memory.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "./device_memory.hpp"
#include "./device.hpp"
using vk::device_memory;
///////////////////////////////////////////////////////////////////////////////
void*
device_memory::map (const device &dev,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags flags)
{
void *res;
auto err = vkMapMemory (dev.id (), id (), offset, size, flags, &res);
error::try_code (err);
return res;
}
//-----------------------------------------------------------------------------
void
device_memory::unmap (const device &dev)
{
vkUnmapMemory (dev.id (), id ());
}
///////////////////////////////////////////////////////////////////////////////
VkDeviceSize
device_memory::commitment (const device &dev) const
{
VkDeviceSize size;
vkGetDeviceMemoryCommitment (dev.id (), id (), &size);
return size;
}

20
device_memory.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef __VK_DEVICE_MEMORY_HPP
#define __VK_DEVICE_MEMORY_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct device_memory : public owned<device_memory,device> {
void* map (const device&,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags flags);
void unmap (const device&);
VkDeviceSize commitment (const device&) const;
};
}
#endif

33
event.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "./event.hpp"
#include "./device.hpp"
using vk::event;
///////////////////////////////////////////////////////////////////////////////
bool
event::is_set (const device &dev) const
{
auto res = vkGetEventStatus (dev.id (), id ());
error::try_code (res);
return res == VK_EVENT_SET;
}
//-----------------------------------------------------------------------------
void
event::set (const device &dev)
{
auto err = vkSetEvent (dev.id (), id ());
error::try_code (err);
}
//-----------------------------------------------------------------------------
void
event::reset (const device &dev)
{
auto err = vkResetEvent (dev.id (), id ());
error::try_code (err);
}

16
event.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef __VK_EVENT_HPP
#define __VK_EVENT_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct event : public owned<event,device> {
bool is_set (const device&) const;
void set (const device&);
void reset (const device&);
};
}
#endif

48
except.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "./except.hpp"
#include <cruft/util/debug.hpp>
using vk::error;
///////////////////////////////////////////////////////////////////////////////
void
error::try_code (VkResult res)
{
if (__builtin_expect (res >= 0, true))
return;
throw_code (res);
}
//-----------------------------------------------------------------------------
void
error::throw_code (VkResult res)
{
switch (res) {
case VK_SUCCESS: throw error_code<VK_SUCCESS> ();
// partial successes
case VK_NOT_READY: throw error_code<VK_NOT_READY> ();
case VK_TIMEOUT: throw error_code<VK_TIMEOUT> ();
case VK_EVENT_SET: throw error_code<VK_EVENT_SET> ();
case VK_EVENT_RESET: throw error_code<VK_EVENT_RESET> ();
case VK_INCOMPLETE: throw error_code<VK_INCOMPLETE> ();
// errors
case VK_ERROR_OUT_OF_HOST_MEMORY: throw error_code<VK_ERROR_OUT_OF_HOST_MEMORY> ();
case VK_ERROR_OUT_OF_DEVICE_MEMORY: throw error_code<VK_ERROR_OUT_OF_DEVICE_MEMORY> ();
case VK_ERROR_INITIALIZATION_FAILED: throw error_code<VK_ERROR_INITIALIZATION_FAILED> ();
case VK_ERROR_DEVICE_LOST: throw error_code<VK_ERROR_DEVICE_LOST> ();
case VK_ERROR_MEMORY_MAP_FAILED: throw error_code<VK_ERROR_MEMORY_MAP_FAILED> ();
case VK_ERROR_LAYER_NOT_PRESENT: throw error_code<VK_ERROR_LAYER_NOT_PRESENT> ();
case VK_ERROR_EXTENSION_NOT_PRESENT: throw error_code<VK_ERROR_EXTENSION_NOT_PRESENT> ();
case VK_ERROR_FEATURE_NOT_PRESENT: throw error_code<VK_ERROR_FEATURE_NOT_PRESENT> ();
case VK_ERROR_INCOMPATIBLE_DRIVER: throw error_code<VK_ERROR_INCOMPATIBLE_DRIVER> ();
case VK_ERROR_TOO_MANY_OBJECTS: throw error_code<VK_ERROR_TOO_MANY_OBJECTS> ();
case VK_ERROR_FORMAT_NOT_SUPPORTED: throw error_code<VK_ERROR_FORMAT_NOT_SUPPORTED> ();
}
unreachable ();
}

23
except.hpp Normal file
View File

@ -0,0 +1,23 @@
#ifndef __VK_EXCEPT_HPP
#define __VK_EXCEPT_HPP
#include "./vk.hpp"
#include <stdexcept>
namespace vk {
class error : public std::exception {
public:
static void try_code (VkResult);
static void throw_code [[noreturn]] (VkResult);
};
template <VkResult>
class error_code : public error {
public:
const char* what (void) const noexcept override;
};
}
#endif

39
fence.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "./fence.hpp"
#include "./device.hpp"
using vk::fence;
///////////////////////////////////////////////////////////////////////////////
bool
fence::is_ready (const device &dev)
{
auto res = vkGetFenceStatus (dev.id (), id ());
error::try_code (res);
return res == VK_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
void
fence::reset (const device &dev, fence *first, fence *last)
{
vkResetFences (dev.id (), last - first, &first->id ());
}
//-----------------------------------------------------------------------------
void
fence::wait (const device &d, fence *first, fence *last, uint64_t timeout)
{
vkWaitForFences (d.id (), last - first, &first->id (), VK_FALSE, timeout);
}
//-----------------------------------------------------------------------------
void
fence::wait_all (const device &d, fence *first, fence *last, uint64_t timeout)
{
vkWaitForFences (d.id (), last - first, &first->id (), VK_TRUE, timeout);
}

16
fence.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef __VK_FENCE_HPP
#define __VK_FENCE_HPP
#include "./object.hpp"
namespace vk {
struct fence : owned<fence,device> {
bool is_ready (const device &dev);
static void reset (const device&, fence *first, fence *last);
static void wait (const device&, fence *first, fence *last, uint64_t timeout);
static void wait_all (const device&, fence *first, fence *last, uint64_t timeout);
};
}
#endif

15
framebuffer.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "./framebuffer.hpp"
#include "./device.hpp"
using vk::framebuffer;
///////////////////////////////////////////////////////////////////////////////
VkExtent2D
framebuffer::area_granularity (const device &dev) const
{
VkExtent2D extent;
vkGetRenderAreaGranularity (dev.id (), id (), &extent);
return extent;
}

12
framebuffer.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef __VK_FRAMEBUFFER_HPP
#define __VK_FRAMEBUFFER_HPP
#include "./object.hpp"
namespace vk {
struct framebuffer : public owned<framebuffer,device> {
VkExtent2D area_granularity (const device&) const;
};
}
#endif

33
fwd.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef __VK_FWD_HPP
#define __VK_FWD_HPP
#include "./vk.hpp"
namespace vk {
template <typename T> struct instantiated;
template <typename T> struct enumerated;
template <typename T, typename O> struct owned;
struct instance;
struct physical_device;
struct device;
struct queue;
struct command_pool;
struct command_buffer;
struct fence;
struct semaphore;
struct event;
struct render_pass;
struct framebuffer;
struct shader_module;
struct pipeline;
struct pipeline_cache;
struct device_memory;
struct buffer;
struct buffer_view;
class error;
template <VkResult> class error_code;
}
#endif

1
image.cpp Normal file
View File

@ -0,0 +1 @@
#include "./image.hpp"

8
image.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef __VK_IMAGE_HPP
#define __VK_IMAGE_HPP
namespace vk {
}
#endif

9
instance.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "./instance.hpp"
using vk::instance;
///////////////////////////////////////////////////////////////////////////////
instance::instance (const VkInstanceCreateInfo &info):
instantiated (&info, nullptr)
{ ; }

15
instance.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef __VK_INSTANCE_HPP
#define __VK_INSTANCE_HPP
#include "./object.hpp"
#include "./vk.hpp"
#include "./traits.hpp"
namespace vk {
struct instance : public instantiated<instance> {
instance (const VkInstanceCreateInfo &info);
};
}
#endif

View File

@ -0,0 +1,25 @@
# SYNOPSIS
#
# NC_APPEND_ONE_COMPILE_FLAG([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# Append the first valid compilation flag in the provided list to FLAGS-VARIABLE
AC_DEFUN([NC_APPEND_ONE_COMPILE_FLAG], [
AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
for __dummy in "1"; do
for flag in $1; do
AX_CHECK_COMPILE_FLAG([$flag],
[AX_APPEND_FLAG([$flag], [$2])
break 2],
[],
[$3])
done
AC_MSG_ERROR([unable to find a valid compilation flag in '$1'])
done
])

27
m4/nc_cxx.m4 Normal file
View File

@ -0,0 +1,27 @@
AC_DEFUN([NC_CXX],[
AX_CHECK_COMPILE_FLAG(
[-std=c++1z],
[AX_APPEND_FLAG([-std=c++1z], [CXXFLAGS])],
[AC_ERROR([Unable to enable c++1z])]
)
AX_APPEND_COMPILE_FLAGS([-pipe], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fno-deduce-init-list], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fno-deduce-init-list], [], [-Werror])
AC_C_CONST
AC_C_RESTRICT
AC_C_INLINE
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([struct A { virtual void C (void) = 0; };
struct B : A { void C (void) override; }; ],
[])],
[], [AC_DEFINE([override], [], [Pretend about override keyword support])])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([struct A final { }; ],
[])],
[], [AC_DEFINE([final], [], [Pretend about final keyword support])])
AX_APPEND_COMPILE_FLAGS([-fvisibility=hidden], [], [-Werror])
])

72
m4/nc_debugging.m4 Normal file
View File

@ -0,0 +1,72 @@
AC_DEFUN([NC_DEBUGGING],[
##-------------------------------------------------------------------------
AX_REQUIRE_DEFINED([AS_HELP_STRING])
AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
AX_REQUIRE_DEFINED([AX_APPEND_LINK_FLAGS])
AX_REQUIRE_DEFINED([NC_APPEND_ONE_COMPILE_FLAG])
##-------------------------------------------------------------------------
AC_ARG_ENABLE([sanitizer], [
AS_HELP_STRING([--enable-sanitizer], [enable memory sanitizer])
])
AS_IF([test "x$enable_sanitizer" = "xyes"], [
m4_foreach([NAME], [
dnl common top-level names. deliberately does not include
dnl 'undefined' due to false positives in some core libraries
dnl (eg, boost::format).
[address],
dnl gcc currently causes segfaults at configure time with [thread],
dnl
dnl gcc specific names. do not use vptr or boost::format will die
[alignment],
[bounds],
[enum],
[float-cast-overflow],
[float-divide-by-zero],
[integer-divide-by-zero],
[leak],
[nonnull-attribute],
[object-size],
[return],
[returns-nonnull-attribute],
[shift],
[signed-integer-overflow],
[unreachable],
[vla-bound],
dnl clang specific names
[integer],
[undefined-trap],
[cfi]dnl
], [
AX_APPEND_COMPILE_FLAGS([-fsanitize=[]NAME], [], [-Werror])
AX_APPEND_LINK_FLAGS([-fsanitize=[]NAME], [], [-Werror])
])
## We, and the std library, tend to use unsigned overflow legitimately
AX_APPEND_COMPILE_FLAGS([-fno-sanitize=unsigned-integer-overflow], [], [-Werror])
AX_APPEND_LINK_FLAGS([-fno-sanitize=unsigned-integer-overflow], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ftrapv], [], [-Werror])
])
##-------------------------------------------------------------------------
AC_ARG_ENABLE([debugging], [
AS_HELP_STRING([--enable-debugging], [enables developer debugging support])
])
AS_IF([test "x${enable_debugging}" = "xyes"], [
AC_DEFINE([ENABLE_DEBUGGING], [], [Debugging support enabled])
AC_DEFINE([_GLIBCXX_DEBUG], [], [Use glibcxx debugging mode])
NC_APPEND_ONE_COMPILE_FLAG([-O0])
], [
AX_APPEND_COMPILE_FLAGS([-O2])
AX_APPEND_COMPILE_FLAGS([-fno-rtti])
AC_DEFINE([NO_RTTI], [], [RTTI disabled])
])
##-------------------------------------------------------------------------
AX_APPEND_COMPILE_FLAGS([-g], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ggdb], [], [-Werror])
])

112
m4/nc_optimisation.m4 Normal file
View File

@ -0,0 +1,112 @@
AC_DEFUN([NC_OPTIMISATION],[
##-------------------------------------------------------------------------
AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
AX_REQUIRE_DEFINED([AC_CANONICAL_HOST])
AX_REQUIRE_DEFINED([AX_COMPILER_VENDOR])
AX_COMPILER_VENDOR
##-------------------------------------------------------------------------
## Enable LTO
AC_ARG_ENABLE([lto], [
AS_HELP_STRING([--enable-lto], [enable link-time optimisation])
])
AS_IF([test "x$enable_lto" == "xyes"], [
AS_IF([test x"${host_os}" == x"mingw32"], [
AC_ERROR([mingw32 link-time optimisation is currently broken])
])
AS_IF([test "x$ax_cv_cxx_compiler_vendor" == "xgnu"], [
AC_CHECK_TOOLS([RANLIB], [gcc-ranlib ranlib])
AC_CHECK_TOOLS([AR], [gcc-ar ar])
AC_CHECK_TOOLS([NM], [gcc-nm nm])
])
AX_APPEND_COMPILE_FLAGS([-flto], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fno-fat-lto-objects], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-flto-odr-type-merging], [], [-Werror])
AX_APPEND_LINK_FLAGS([-fuse-linker-plugin], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fdevirtualize-at-ltrans], [], [-Werror])
])
##-------------------------------------------------------------------------
## Enable frame pointer
AC_ARG_ENABLE([frame-pointer], [
AS_HELP_STRING([--enable-frame-pointer], [retain the frame pointer even if optimising])
])
AS_IF([test "x$enable_frame_pointer" = "xyes"], [
AX_APPEND_COMPILE_FLAGS([-fno-omit-frame-pointer], [], [-Werror])
])
##-------------------------------------------------------------------------
## Choose the most performant processor architecture and features
AC_CANONICAL_HOST
AS_CASE([$host_cpu],
[x86_64], [
AX_APPEND_COMPILE_FLAGS([-mtune=generic], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-msse], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-msse2], [], [-Werror])
],
[i686], [
AX_APPEND_COMPILE_FLAGS([-march=prescott], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-mtune=generic], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-mcmov], [], [-Werror])
],
[AC_MSG_WARN([unknown host_cpu])]
)
AX_APPEND_COMPILE_FLAGS([-pipe])
# base instruction set requirements for x86
AX_APPEND_COMPILE_FLAGS([-mfpmath=sse], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-msahf], [], [-Werror])
##-------------------------------------------------------------------------
## Enable aggressive code generation optimisations
AS_IF([test "x$enable_debugging" != "xyes"], [
# gcc vectorisation
AX_APPEND_COMPILE_FLAGS([-ftree-vectorize], [], [-Werror])
# clang vectorisation
AX_APPEND_COMPILE_FLAGS([-fvectorize], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fslp-vectorize], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fslp-vectorize-aggressive], [], [-Werror])
# loop hosting/distribution
AX_APPEND_COMPILE_FLAGS([-ftree-loop-distribute-patterns], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ftree-loop-distribution], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ftree-loop-if-convert-stores], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ftree-loop-linear], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-funsafe-loop-optimizations], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-floop-interchange], [], [-Werror])
# safety removal for performance
AX_APPEND_COMPILE_FLAGS([-fno-stack-protector], [], [-Werror])
])
##-------------------------------------------------------------------------
## Enable code size optimisations (that don't impact performance)
## Note: we assume CXX, and that CXXLINK is g++ not ld, hence the -Wl opt
AS_IF([test "x$enable_debugging" != "xyes"], [
AX_APPEND_COMPILE_FLAGS([-fdevirtualize], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fdevirtualize-speculatively], [], [-Werror])
AX_CHECK_LINK_FLAG([-Wl,--gc-sections], [
AX_APPEND_COMPILE_FLAGS([-fdata-sections], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-ffunction-sections], [], [-Werror])
AX_APPEND_LINK_FLAGS([-Wl,--gc-sections], [], [-Werror])
])
])
])

28
m4/nc_platform.m4 Normal file
View File

@ -0,0 +1,28 @@
AC_DEFUN([NC_PLATFORM],[
AC_CANONICAL_HOST
AM_CONDITIONAL([PLATFORM_WIN32], [test "x$host_os" = "xmingw32"])
AM_CONDITIONAL([PLATFORM_LINUX], [test "x$host_os" = "xlinux-gnu"])
AS_CASE([$host_os],
[mingw32], [
AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
AC_CHECK_HEADERS([windows.h],[],[],[AC_INCLUDES_DEFAULT])
AC_SUBST([NET_LIBS], [-lws2_32])
AX_APPEND_COMPILE_FLAGS([-DBOOST_THREAD_USE_LIB], [], [-Werror])
## Force as many static libraries as possible to avoid bullshit libc
## cross-library memory management issues.
AX_APPEND_LINK_FLAGS([-static-libstdc++], [], [-Werror])
AX_APPEND_LINK_FLAGS([-static-libgcc], [], [-Werror])
],
[linux-gnu], [ ],
[AC_MSG_ERROR([Unknown platform])]
)
AX_APPEND_COMPILE_FLAGS([-fno-common], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-fno-nonansi-builtins], [], [-Werror])
])

81
m4/nc_warnings.m4 Normal file
View File

@ -0,0 +1,81 @@
AC_DEFUN([NC_WARNINGS],[
AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS])
AX_REQUIRE_DEFINED([AX_COMPILER_VENDOR])
AX_COMPILER_VENDOR
# -------------------------------------------------------------------------
# Compound warnings
AX_APPEND_COMPILE_FLAGS([-Wall], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wextra], [], [-Werror])
# -------------------------------------------------------------------------
# General warnings
AX_APPEND_COMPILE_FLAGS([-Wbool-compare], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wcast-align], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wcast-qual], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wdisabled-optimization], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wfloat-conversion], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wfloat-equal], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-aggressive-loop-optimizations], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wnoexcept], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wnon-virtual-dtor], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-parentheses], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wpointer-arith], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wredundant-decls], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wshadow], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wsign-compare], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wsign-promo], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wstrict-aliasing], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wstrict-overflow], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wtype-limits], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wunsafe-loop-optimizations], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wunused-but-set-variable], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wunused-parameter], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wuseless-cast], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wpessimizing-move], [], [-Werror])
# -------------------------------------------------------------------------
# Required extensions
#AX_APPEND_COMPILE_FLAGS([-Wgnu-flexible-array-union-member], [], [-Werror])
#AX_APPEND_COMPILE_FLAGS([-Wno-c99-extensions], [], [-Werror])
#AX_APPEND_COMPILE_FLAGS([-Wno-vla-extension], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-vla], [], [-Werror])
AS_IF([test "x$ax_cv_cxx_compiler_vendor" != "xgnu"], [
AX_APPEND_COMPILE_FLAGS([-Wno-c99-extensions], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-flexible-array-extensions], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-gnu-conditional-omitted-operand], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-gnu-empty-struct], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-gnu-flexible-array-union-member], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-gnu-zero-variadic-macro-arguments], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-vla-extension], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-zero-length-array], [], [-Werror])
])
# -------------------------------------------------------------------------
# Excessive warnings
AX_APPEND_COMPILE_FLAGS([-Wno-missing-braces], [], [-Werror])
AS_IF([test "x$ax_cv_cxx_compiler_vendor" != "xgnu"], [
AX_APPEND_COMPILE_FLAGS([-Wno-nested-anon-types], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wno-unused-const-variable], [], [-Werror])
])
# -------------------------------------------------------------------------
# Strict warnings
AX_APPEND_COMPILE_FLAGS([-pedantic], [], [-Werror])
# -------------------------------------------------------------------------
# Advisory warnings
AC_ARG_ENABLE([advisory], [
AS_HELP_STRING([--enable-advisory], [enable advisory warnings])
])
AS_IF([test "x$enable_advisory" = "xyes"], [
AX_APPEND_COMPILE_FLAGS([-Winline], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wsuggest-final-types], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wsuggest-final-methods], [], [-Werror])
AX_APPEND_COMPILE_FLAGS([-Wsuggest-override], [], [-Werror])
], [])
])

1
object.cpp Normal file
View File

@ -0,0 +1 @@
#include "./object.hpp"

56
object.hpp Normal file
View File

@ -0,0 +1,56 @@
#ifndef __VK_OBJECT_HPP
#define __VK_OBJECT_HPP
#include "./traits.hpp"
#include "./except.hpp"
#include <utility>
namespace vk {
template <typename T>
struct object {
using id_t = typename id_traits<T>::id_t;
object (id_t);
id_t& id (void) const&;
private:
id_t m_id;
};
template <typename T>
struct instantiated : public object<T> {
using id_t = typename object<T>::id_t;
template <typename ...Args>
instantiated (Args &&...args):
object<T> (make (std::forward<Args> (args)...))
{ ; }
~instantiated ()
{
life_traits<T>::destroy (this->id (), nullptr);
}
private:
template <typename ...Args>
static
id_t make (Args &&...args)
{
id_t id;
auto res = life_traits<T>::create (std::forward<Args> (args)..., &id);
error::try_code (res);
return id;
}
};
template <typename T>
struct enumerated : public object<T> { };
template <typename T, typename O>
struct owned : public object<T> { };
}
#endif

3
physical_device.cpp Normal file
View File

@ -0,0 +1,3 @@
#include "physical_device.hpp"
///////////////////////////////////////////////////////////////////////////////

13
physical_device.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef __VK_PHYSICAL_DEVICE_HPP
#define __VK_PHYSICAL_DEVICE_HPP
#include "./object.hpp"
#include "./vk.hpp"
namespace vk {
struct physical_device : public enumerated<physical_device> {
};
}
#endif

7
pipeline.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "./pipeline.hpp"
using vk::pipeline;
///////////////////////////////////////////////////////////////////////////////

13
pipeline.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef __VK_PIPELINE_HPP
#define __VK_PIPELINE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct pipeline : public owned<pipeline,device> {
};
}
#endif

17
pipeline_cache.cpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef __VK_PIPELINE_CACHE_HPP
#define __VK_PIPELINE_CACHE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct pipeline_cache : public owned<pipeline_cache,device> {
void merge (const device&,
const pipeline_cache *first,
const pipeline_cache *last);
size_t get (const device&, void *dst, size_t len) const;
};
}
#endif

26
pipeline_cache.hpp Normal file
View File

@ -0,0 +1,26 @@
#include "./pipeline_cache.hpp"
#include "./device.hpp"
using vk::pipeline_cache;
///////////////////////////////////////////////////////////////////////////////
void
pipeline_cache::merge (const device &dev,
const pipeline_cache *first,
const pipeline_cache *last)
{
auto err = vkMergePipelineCache (dev.id (), id (), last - first, &first->id ());
error::try_code (err);
}
///////////////////////////////////////////////////////////////////////////////
size_t
pipeline_cache::get (const device &dev, void *dst, size_t len)
{
auto err = vkGetPipelineCacheData (dev.id (), id (), dst, &len);
error::try_code (err);
return len;
}

18
queue.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "./queue.hpp"
#include "./except.hpp"
using vk::queue;
///////////////////////////////////////////////////////////////////////////////
void
queue::wait_idle (void)
{
auto err = vkQueueWaitIdle (id ());
error::try_code (err);
}
///////////////////////////////////////////////////////////////////////////////

16
queue.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef __VK_QUEUE_HPP
#define __VK_QUEUE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct queue : public owned<queue,device> {
void wait_idle (void);
template <typename T>
void submit (T data, const fence&); // VkQueueSubmit
};
}
#endif

1
render_pass.cpp Normal file
View File

@ -0,0 +1 @@
#include "./render_pass.hpp"

12
render_pass.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef __VK_RENDER_PASS_HPP
#define __VK_RENDER_PASS_HPP
#include "./object.hpp"
namespace vk {
struct render_pass : public owned<render_pass,device> {
};
}
#endif

1
semaphore.cpp Normal file
View File

@ -0,0 +1 @@
#include "./semaphore.hpp"

13
semaphore.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef __VK_SEMAPHORE_HPP
#define __VK_SEMAPHORE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct semaphore : public owned<semaphore,device> {
};
}
#endif

1
shader_module.cpp Normal file
View File

@ -0,0 +1 @@
#include "./shader_module.hpp"

13
shader_module.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef __VK_SHADER_MODULE_HPP
#define __VK_SHADER_MODULE_HPP
#include "./object.hpp"
#include "./fwd.hpp"
namespace vk {
struct shader_module : public owned<shader_module,device> {
};
}
#endif

113
traits.hpp Normal file
View File

@ -0,0 +1,113 @@
#ifndef __VK_TRAITS_HPP
#define __VK_TRAITS_HPP
#include "./fwd.hpp"
#include "./vk.hpp"
namespace vk {
///////////////////////////////////////////////////////////////////////////
template <typename T> struct id_traits { };
template <> struct id_traits<instance> { using id_t = VkInstance; };
template <> struct id_traits<physical_device> { using id_t = VkPhysicalDevice; };
template <> struct id_traits<device> { using id_t = VkDevice; };
template <> struct id_traits<queue> { using id_t = VkQueue; };
template <> struct id_traits<command_pool> { using id_t = VkCommandPool; };
template <> struct id_traits<command_buffer> { using id_t = VkCommandBuffer; };
template <> struct id_traits<fence> { using id_t = VkFence; };
template <> struct id_traits<semaphore> { using id_t = VkSemaphore; };
template <> struct id_traits<event> { using id_t = VkEvent; };
template <> struct id_traits<render_pass> { using id_t = VkRenderPass; };
template <> struct id_traits<framebuffer> { using id_t = VkFramebuffer; };
template <> struct id_traits<shader_module> { using id_t = VkShaderModule; };
template <> struct id_traits<pipeline> { using id_t = VkPipeline; };
template <> struct id_traits<pipeline_cache> { using id_t = VkPipelineCache; };
template <> struct id_traits<device_memory> { using id_t = VkDeviceMemory; };
template <> struct id_traits<buffer> { using id_t = VkBuffer; };
template <> struct id_traits<buffer_view> { using id_t = VkBufferView; };
///////////////////////////////////////////////////////////////////////////
template <typename T> struct life_traits { };
template <> struct life_traits<instance> {
static constexpr auto create = vkCreateInstance;
static constexpr auto destroy = vkDestroyInstance;
};
template <> struct life_traits<device> {
static constexpr auto create = vkCreateDevice;
static constexpr auto destroy = vkDestroyDevice;
};
template <> struct life_traits<command_pool> {
static constexpr auto create = vkCreateCommandPool;
static constexpr auto destroy = vkDestroyCommandPool;
};
template <> struct life_traits<fence> {
static constexpr auto create = vkCreateFence;
static constexpr auto destroy = vkDestroyFence;
};
template <> struct life_traits<semaphore> {
static constexpr auto create = vkCreateSemaphore;
static constexpr auto destroy = vkDestroySemaphore;
};
template <> struct life_traits<event> {
static constexpr auto create = vkCreateEvent;
static constexpr auto destroy = vkDestroyEvent;
};
template <> struct life_traits<render_pass> {
static constexpr auto create = vkCreateRenderPass;
static constexpr auto destroy = vkDestroyRenderPass;
};
template <> struct life_traits<framebuffer> {
static constexpr auto create = vkCreateFramebuffer;
static constexpr auto destroy = vkDestroyFramebuffer;
};
template <> struct life_traits<shader_module> {
static constexpr auto create = vkCreateShaderModule;
static constexpr auto destroy = vkDestroyShaderModule;
};
template <VkPipelineBindPoint> struct create_traits { };
template <> struct create_traits<VK_PIPELINE_BIND_POINT_COMPUTE> {
static constexpr auto func = vkCreateComputePipelines;
};
template <> struct create_traits<VK_PIPELINE_BIND_POINT_GRAPHICS> {
static constexpr auto func = vkCreateGraphicsPipelines;
};
template <> struct life_traits<pipeline> {
template <VkPipelineBindPoint P>
static constexpr auto create = create_traits<P>::func;
static constexpr auto destroy = vkDestroyPipeline;
};
template <> struct life_traits<pipeline_cache> {
static constexpr auto create = vkCreatePipelineCache;
static constexpr auto destroy = vkDestroyPipelineCache;
};
template <> struct life_traits<device_memory> {
static constexpr auto create = vkAllocateMemory;
static constexpr auto destroy = vkFreeMemory;
};
template <> struct life_traits<buffer> {
static constexpr auto create = vkCreateBuffer;
static constexpr auto destroy = vkDestroyBuffer;
};
template <> struct life_traits<buffer_view> {
static constexpr auto create = vkCreateBufferView;
};
}
#endif

5099
vk.xml Normal file

File diff suppressed because it is too large Load Diff

178
vk.xsl Normal file
View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<!-- type declarations -->
<xsl:template match="type[@category='basetype']">
using <xsl:value-of select="name" /> = <xsl:value-of select="type" />;
</xsl:template>
<xsl:template match="type[@category='bitmask']">
using <xsl:value-of select="name" /> = <xsl:value-of select="type" />;
</xsl:template>
<xsl:template match="type[@category='handle']">
// actually a 64 bit pointer
// should make use of parent info
using <xsl:value-of select="name" /> = uint64_t;
</xsl:template>
<xsl:template match="type[@category='funcpointer']">
// should make use of function parameters
typedef void (*<xsl:value-of select="name" />) (void);
</xsl:template>
<xsl:template match="type[@category='struct']">
struct <xsl:value-of select="@name" /> {
<xsl:for-each select="member">
<xsl:for-each select=".//text()">
<xsl:value-of select="." />
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:text>;</xsl:text>
</xsl:for-each>
};
</xsl:template>
<xsl:template match="type[@category='union']">
// should make use of member types
union <xsl:value-of select="@name" /> {
<xsl:for-each select="member">
<xsl:value-of select="type"/>
<xsl:text> </xsl:text>
<xsl:value-of select="name" />
<xsl:text>;</xsl:text>
</xsl:for-each>
};
</xsl:template>
<!-- we have to define these system types manually because they aren't consistent types -->
<xsl:template match="type[not(@category) and @requires and @name]" />
<xsl:template match="type[@category='define']" /> <!-- we handle defines manually -->
<xsl:template match="type[@category='enum']"/> <!-- handed where the values are declared -->
<xsl:template match="type[@category='include']" /> <!-- we can't arbitrarily include headers in a platform independant way -->
<xsl:template match="types">
<xsl:apply-templates />
</xsl:template>
<!-- enumerations -->
<xsl:template match="enums[@name='API Constants']">
<xsl:for-each select="enum">
constexpr auto <xsl:value-of select="@name" /> = <xsl:value-of select="@value" />;
</xsl:for-each>
</xsl:template>
<xsl:template match="enums[@type='enum']">
// make use of @expand
enum <xsl:value-of select="@name" /> {
<xsl:for-each select="enum">
<xsl:value-of select="@name"/> = <xsl:value-of select="@value"/>,
</xsl:for-each>
};
</xsl:template>
<xsl:template match="enums[@type='bitmask']">
enum <xsl:value-of select='@name'/> {
<xsl:for-each select="enum">
<xsl:choose>
<xsl:when test="@bitpos">
<xsl:value-of select="@name"/> = 1UL &lt;&lt; <xsl:value-of select="@bitpos" />
</xsl:when>
<xsl:when test="@value">
<xsl:value-of select="@name"/> = <xsl:value-of select="@value" />
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
#error Unhandle enum type for <xml:value-of select="name()" />
</xsl:message>
</xsl:otherwise>
</xsl:choose>,
</xsl:for-each>
};
</xsl:template>
<!-- public functions -->
<xsl:template match="command">
<xsl:value-of select="proto/type" />
<xsl:text> </xsl:text>
<xsl:value-of select="proto/name" /> (
<xsl:for-each select="param">
<xsl:for-each select=".//text()">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
);
</xsl:template>
<!-- elements we don't care about just yet -->
<xsl:template match="extensions" />
<xsl:template match="feature" />
<xsl:template match="comment" />
<xsl:template match="vendorids" />
<xsl:template match="tags" />
<!-- top level sectioning commands we just want to iterate over -->
<xsl:template match="commands">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="registry">
<xsl:text>
#ifndef __VK_HPP
#define __VK_HPP
#include &lt;cstdint&gt;
#include &lt;cstddef&gt;
struct Display;
struct VisualID;
using Window = unsigned long;
struct ANativeWindow;
struct MirConnection;
struct MirSurface;
struct wl_display;
struct wl_surface;
using HANDLE = void*;
using HINSTANCE = HANDLE;
using HWND = HANDLE;
struct xcb_connection_t;
struct xcb_visualid_t;
using xcb_window_t = uint32_t;
</xsl:text>
<!-- deliberately instane enums before types, as the latter depends on the former -->
<xsl:apply-templates select="comment"/>
<xsl:apply-templates select="vendorids"/>
<xsl:apply-templates select="tags"/>
<xsl:apply-templates select="enums"/>
<xsl:apply-templates select="types"/>
<xsl:apply-templates select="commands"/>
<xsl:apply-templates select="feature"/>
<xsl:apply-templates select="extensions"/>
<xsl:text>
#endif
</xsl:text>
</xsl:template>
<xsl:template match="*/text()" />
<xsl:template match="*">
<xml:message terminate="no">
#error Unmatched element &lt;<xsl:value-of select="name()"/> <xsl:for-each select="@*"><xsl:value-of select="name()" />=<xsl:value-of select="." /></xsl:for-each>&gt;
</xml:message>
</xsl:template>
</xsl:stylesheet>