+ All Categories
Home > Documents > VKCPP -...

VKCPP -...

Date post: 30-Sep-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
39
April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology Engineer [email protected] 4/4/2016 VKCPP
Transcript
Page 1: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

April 4-7, 2016 | Silicon Valley

Markus Tavenrath

Senior Developer Technology Engineer

[email protected]

4/4/2016

VKCPP

Page 2: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

2

INTRODUCTION

Senior Dev Tech Software Engineer - Professional Visualization

Joined NVIDIA 8 years ago to work on middleware

Goal: Make GPU programming easy and efficient

Working with CAD ISVs to optimizing their graphics pipelines

Working with driver team on Vulkan and OpenGL performance

Who am I?

Page 3: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

3

INTRODUCTIONWhat is Vulkan?

4/4/2016

Clean, modern and consistent C-API without cruft

Low CPU overhead

Scales well with multiple threads

Provides ‚low level‘ control over GPU

Moves a lot of responsibility from driver to developer

Developer essentialy writes part of the driver

Page 4: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

4

HELLO VULKAN

4/4/2016

Simple HelloVulkan is ~750 lines of code

So much to do, hard to start

Easy to make errors

Even harder to find those errors

Is there a way to simplify Vulkan usage?

Two projects started

VKCPP (low level C++ API)

NVK* (high level C++ API)

Page 5: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

5

VKCPPhttp://github.com/nvpro-pipeline/vkcpp

VKCPP is a port of the Vulkan API for C++11

Simplifies logic where possible without changing concepts/behaviour

Generated from the official Vulkan spec file, vk.xml

Header only with inline functions to minimize additional cost

Open source project contains generated header and generator

4/4/2016

Page 6: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

6

VKCPP GOALSReduce code size & risk of errors

Initialization ‚vertical‘

-> reduced clearness due to #lines on screen

Potential issues

Struct/sType enums mismatch

No type safety for enums and flags

Risk of uninitialized fields

VkApplicationInfo appInfo = {};

appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;

appInfo.pNext = NULL;

appInfo.pApplicationName = appName;

appInfo.applicationVersion = 1;

appInfo.pEngineName = engineName;

appInfo.engineVersion = 1;

appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 5);

VkInstanceCreateInfo instInfo = {};

instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

instInfo.pNext = NULL;

instInfo.flags = 0;

instInfo.pApplicationInfo = &appInfo;

instInfo.enabledLayerCount = layerNames.size();

instInfo.ppEnabledLayerNames = layerNames.data()

instInfo.enabledExtensionCount = extensionNames.size();

instInfo.ppEnabledExtensionNames = extensionNames.data();

VkResult res = vkCreateInstance(&instInfo, NULL, &info.inst);

assert(res == VK_SUCCESS);

Page 7: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

7

VULKAN NAMESPACE

// Strip Vk prefix of all functions and structs

VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,

const VkAllocationCallbacks* pAllocator,

VkInstance* pInstance);

// Introduce new vk namespace for all vkcpp symbols

namespace vk {

Result createInstance(const InstanceCreateInfo* pCreateInfo,

const AllocationCallbacks* pAllocator,

Instance* pInstance);

};

avoid symbol collisions

Page 8: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

8

TYPE SAFETYEnums

namespace vk

{

// Use scoped enums for type safety

enum class ImageType

{

e1D = VK_IMAGE_TYPE_1D,

e2D = VK_IMAGE_TYPE_2D,

e3D = VK_IMAGE_TYPE_3D

};

}

Strip VK_ prefix + enum name

Use upper camel case of enum type as name

‘e‘ + name

prefix is required only for numbers, used everywhere for consistency reasons

Page 9: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

9

TYPE SAFETYFlags

4/4/2016

// Introduce class for typesafe flags

template <typename BitType, typename MaskType = VkFlags>

class Flags {

...

};

// BitType is scoped enum

enum class QueueFlagBits {

eGraphics = VK_QUEUE_GRAPHICS_BIT,

eCompute = VK_QUEUE_COMPUTE_BIT,

eTransfer = VK_QUEUE_TRANSFER_BIT,

eSparseBinding = VK_QUEUE_SPARSE_BINDING_BIT

};

// Define typesafe flags

typedef Flags<QueueFlagBits, VkQueueFlags> QueueFlags;

Page 10: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

10

TYPE SAFETYFlags

template <typename BitType, typename MaskType = VkFlags>

class Flags {

public:

Flags(); // No flags set. Use QueueFlags() or {} as value

Flags(BitType bit); // QueueFlags qf(QueueFlagBits::eGraphics)

Flags<BitType> & operator|=(Flags<BitType> const& rhs); // qf |= QueueFlagBits::eCompute;

Flags<BitType> & operator&=(Flags<BitType> const& rhs); // qf &= QueueFlagBits::eGraphics;

Flags<BitType> & operator^=(Flags<BitType> const& rhs); // qf ^= QueueFlagBits::eGraphics;

Flags<BitType> operator|(Flags<BitType> const& rhs) const; // qf = QueueFlagBits::eCompute | QueueFlagBits::eGraphics

Flags<BitType> operator&(Flags<BitType> const& rhs) const; // qf = qf & QueueFlagBits::eGraphics

Flags<BitType> operator^(Flags<BitType> const& rhs) const; // qf = qf ^ QueueFlagBits::eGraphics

explicit operator bool() const; // if (qf) Is any bit set?

bool operator!() const; // if (!qf) Is no bit set?

bool operator==(Flags<BitType> const& rhs) const; // if (qt == QueueFlagBits::eCompute)

bool operator!=(Flags<BitType> const& rhs) const; // if (qt != QueueFlagBits::eCompute)

explicit operator MaskType() const; // VkFlags flags = static_cast<VkFlags>(qf);

};

Page 11: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

11

INITIALIZATIONCreateInfos and Structs

4/4/2016

class EventCreateInfo

{

public:

// All constructors initialize sType/pNext

EventCreateInfo(); // Initialize all fields with default values (0 currently)

EventCreateInfo(EventCreateFlags flags); // Create with all parameters specified

EventCreateInfo(VkEventCreateInfo const & rhs); // Construct from native Vulkan type

// get parameter object

const EventCreateFlags& flags() const;

EventCreateFlags& flags(); // get parameter from non-cost object

// set parameter

EventCreateInfo& flags(EventCreateFlags flags);

...

operator const VkEventCreateInfo&() const; // cast operator to native vulkan type

};

Page 12: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

12

RESULTSCODE SIZE & TYPE SAFETY

vk::ApplicationInfo appInfo(appName, 1,

engineName, 1,

VK_MAKE_VERSION(1,0,5));

vk::InstanceCreateInfo i({}, &appInfo,

layerNames.size(), layerNames.data(),

extNames.size(), extNames.data());

vk::Instance instance;

vk::Result res = vk::createInstance(&i, nullptr, &instance);

assert(res == vk::Result::eSuccess);

VkApplicationInfo appInfo = {};

appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;

appInfo.pNext = NULL;

appInfo.pApplicationName = appName;

appInfo.applicationVersion = 1;

appInfo.pEngineName = engineName;

appInfo.engineVersion = 1;

appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 5);

VkInstanceCreateInfo i = {};

i.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

i.pNext = NULL;

i.flags = 0;

i.pApplicationInfo = &appInfo;

i.enabledLayerCount = layerNames.size();

i.ppEnabledLayerNames = layerNames.data()

i.enabledExtensionCount = extNames.size();

i.ppEnabledExtensionNames = extNames.data();

VkInstance instance;

VkResult res = vkCreateInstance(&i, NULL, &instance);

assert(res == VK_SUCCESS);

Page 13: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

13

RESULTSCODE SIZE & TYPE SAFETY

4/4/2016

vk::ApplicationInfo appInfo(appName, 1,

engineName, 1,

VK_MAKE_VERSION(1,0,5));

vk::InstanceCreateInfo i({}, &appInfo,

layerNames.size(), layerNames.data(),

extNames.size(), extNames.data());

vk::Instance instance;

vk::Result res = vk::createInstance(&i, nullptr, &instance);

assert(res == vk::Result::eSuccess);

std::vector<std::string>?

Bad idea

vk::InstanceCreateInfo i({}, &appInfo,

{“layer_xyz”},

extNames.size(), extNames.data());

Lifetime of struct != Lifetime of temporaryTemporary array will be destroyed after

constructor

CreateInfos would have to copy data

Page 14: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

14

DESIGNATED INITIALIZER LIST

4/4/2016

VkApplicationInfo appInfo =

{

.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,

.pNext = NULL,

.pApplicationName = appName,

.applicationVersion = 1,

.pEngineName = engineName,

.engineVersion = 1,

.apiVersion = VK_MAKE_VERSION(1,0,5)

};

vk::ApplicationInfo appInfo = vk::ApplicationInfo()

.pApplicationName(appName)

.applicationVersion(1)

.pEngineName(engineName)

.engineVersion(1)

.apiVersion(VK_MAKE_VERSION(1,0,5));

Designated initializer list not part of C++11

Names explicit, but no guarantee to set all fields

Page 15: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

15

C++ CODING STYLEHANDLES

4/4/2016

VkCommandBuffer cmd = ...

VkRect2D scissor;

scissor.offset.x = 0;

scissor.offset.y = 0;

scissor.extent.width = width;

scissor.extent.height = height;

vkCmdSetScissor(cmd, 0, 1, &scissor);

Convert C-Style OOto

C++ Style OO

class CommandBuffer{

// conversion from/to native handleCommandBuffer(VkCommandBuffer commandBuffer);CommandBuffer& operator=(VkCommandBuffer

commandBuffer);operator VkCommandBuffer() const;

// boolean tests if handle is validexplicit operator bool() const;bool operator!() const;

// functionsvoid setScissor(uint32_t firstScissor,

uint32_t scissorCount,const Rect2D* pScissors) const;

};vk::CommandBuffer cmd;

cmd.setScissor(0, 1, &scissor);

Page 16: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

16

C++ CODING STYLETEMPORARY STRUCTS AND EXCEPTIONS

4/4/2016

class Device {

Result createFence(const FenceCreateInfo * createInfo, AllocationCallbacks const * allocator, Fence * fence) const;

};

Change from pointer to referenceallows passing temporaries

class Device {

Fence createFence(const FenceCreateInfo & createInfo, Optional<AllocationCallbacks const> const & allocator) const;

};

Page 17: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

17

C++ CODING STYLETEMPORARY STRUCTS AND EXCEPTIONS

4/4/2016

class Device {

Result createFence(const FenceCreateInfo * createInfo, AllocationCallbacks const * allocator, Fence * fence) const;

};

AllocationCallbacks are optional and might be nullOptional<Allocationcallbacks> accepts nullptr as input

class Device {

Fence createFence(const FenceCreateInfo & createInfo, Optional<AllocationCallbacks const> const & allocator) const;

};

Page 18: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

18

C++ CODING STYLEOptional References and Return Values

4/4/2016

class Device {

Result createFence(const FenceCreateInfo * createInfo, const AllocationCallbacks * allocator, Fence * fence) const;

};

Fence is now a return valueThe C++ version of the function throws a std::system-error if result is not a success code

class Device {

Fence createFence(const FenceCreateInfo & createInfo, Optional<AllocationCallbacks const> const & allocator) const;

};

Page 19: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

19

C++ CODING STYLERESULTS

4/4/2016

vk::Fence fence;

vk::FenceCreateInfo ci;

vk::Result result = device.createFence(&ci, nullptr, &fence);

assert(result == vk::Result::eSuccess);

try {

vk::Fence fence = device.createFence({}, nullptr);

} catch (std::system_error e) {...}

Page 20: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

20

C++ CODING STYLERESULTS

4/4/2016

vk::Fence fence;

vk::FenceCreateInfo ci;

vk::Result result = device.createFence(&ci, nullptr, &fence);

assert(result == vk::Result::eSuccess);

vk::Fence fence = device.createFence({}, nullptr);

Page 21: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

21

C++ CODING STYLEARRAYS

4/4/2016

VkCommandBuffer cmd = ...

VkRect2D scissor;

scissor.offset.x = 0;

scissor.offset.y = 0;

scissor.extent.width = width;

scissor.extent.height = height;

cmd.setScissor(0, 1, &scissor);

class CommandBuffer{

// additional functions for arrays

void setScissor(uint32_t firstScissor,

std::vector<Rect2D> const & scissors)

const;

};

VkCommandBuffer cmd = ...

cmd.setScissor(0, { { {0u,0u}, {width, height} } });

Offset2D Extent2D

Rect2D

std::vector<Rect2D>

Count and real data size always correctLifetime of temporary is function call

Page 22: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

22

C++ CODING STYLEDynamically sized queries

vk::PhysicalDevice pd = ...;

std::vector<vk::QueueFamilyProperties> properties;

uint32_t queueCount;

pd.getQueueFamilyProperties(&queueCount, nullptr);

properties.resize(queueCount);

pd.getQueueFamilyProperties(&queueCount, properties.data());

Define variables

Query size

Resize std::vector

Query data

vk::PhysicalDevice pd = ...;

std::vector<vk::QueueFamilyProperties> properties = pd.getQueueFamilyProperties();

Page 23: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

23

C++ CODING STYLEDynamically sized queries

std::vector<vk::ExtensionProperties> properties = enumerateInstanceExtensionProperties(layer);

vk::Result res;

std::vector<vk::ExtensionProperties> properties;

uint32_t count;

char *layer = ...;

do {

res = vk::enumerateInstanceExtensionProperties(layer, &count, nullptr);

if (res) throw error;

properties.resize(count);

res = vk::enumerateInstanceExtensionProperties(layer, &count, properties.data());

} while (res == vk::Result::eIncomplete);

Page 24: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

24

C++ CODING STYLEupdateBuffer

class CommandBuffer {

void updateBuffer(Buffer dstBuffer, DeviceSize dstOffset,

DeviceSize dataSize, const uint32_t* pData) const;

};

cmd.updateBuffer(buffer, 0,

static_cast<DeviceSize>(data.size() * sizeof(*data.data())),

reinterpret_cast<const uint32_t*>(data.data()));

Might work or might not work if sizeof(*data.data()) is not a multiple of 4

Call is not that beautiful

dataSize in bytes data type is uint32_t -> dataSize must be multiple of 4

Page 25: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

25

C++ CODING STYLEupdateBuffer

4/4/2016

class CommandBuffer {

template <typename T>

void updateBuffer(Buffer dstBuffer, DeviceSize dstOffset,

std::vector<T> const & data) const;

};

cmd.updateBuffer(buffer, 0, data); static_assert to ensure sizeof(T) is a multiple of 4-> compile time failure instead of runtime failure

Page 26: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

26

UTILITY FUNCTIONSto_string

For debugging purposes it‘s useful to convert enums or flags to strings

std::string to_string(FooEnum value) for enums

to_string(vk::Result::eSuccess)-> “Success”

std::string to_string(BarFlags value) for flags

to_string(vk::QueueFlagBits::eGraphics | vk::QueueFlagBits::eCompute)-> “Graphics | Compute”

Page 27: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

27

VKCPP

VKCPP is ‘raw vulkan‘ using C++11 features

Increases type safety and construction safety at compile time

Also provides syntactic sugar

Classes for handles

Tempoaries for parameters

std::vector for arrays

Utility functions (to_string)

Good for experts, doesn‘t simplify Vulkan workflow

Conclusion

Page 28: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

28

NVKMotivation

Vulkan starters just want to render a triangle

NVK will provide utility functions for routine work

Resource Tracking CPU and GPU, lifetime can be hard to handle

Memory suballocation, everyone will have to do it

Utility functions, i.e. setup framebuffer

Project at early stages, Hello Vulkan already ported ;-)

4/4/2016

Page 29: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

29

NVKHierarchy

4/4/2016

Instance

DeviceMemory … Image

PhysicalDevice

Device

std::shared_ptrto parent

Queue

Resources

Destroy DeviceDestroy Image

vkDestroyImage(m_device, …);

Page 30: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

30

NVKHierarchy

4/4/2016

Instance

DeviceMemory … Image

PhysicalDevice

Device

std::weak_ptr

std::shared_ptr

Queue

Resources

PhysicalDevice and Queue exist

No need for destruction

Reference to parent required

Weak_ptr allows identity check

Page 31: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

31

NVKHierarchy

Implemented RAII layer with shared_ptrs

Lifetime tracking

Exception safety

CreateInfos replaced by create function with parameters

std::shared_ptr<nvk::Instance> instance = nvk::Instance::create(“nvk", 0, ...);

4/4/2016

Page 32: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

32

NVKMemory Suballocation

4/4/2016

It‘s strongly recommended to do suballocations in Vulkan

Make nvk::DeviceMemory suballocation aware

class DeviceMemory {vk::DeviceMemory deviceMemory;vk::DeviceSize offset;...

};

Made API using DeviceMemory suballocation aware

nvk::bindImageMemory(deviceMemory, image, offset) gets

vk::bindImageMemory(deviceMemory, image, offset + deviceMemory.offset)

Page 33: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

33

NVKMemory Suballocation

4/4/2016

Introduce Heap interface

class Heap {

virtual std::shared_ptr<nvk::DeviceMemory>

allocate(vk::MemoryRequirements const & requirements) = 0;

};

Interface allows multiple strategies for small/large or fixed size allocations

Page 34: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

34

NVKMemory Suballocation

There‘s no free in the interface

class Heap {

virtual std::shared_ptr<nvk::DeviceMemory>

allocate(vk::MemoryRequirements const & requirements) = 0;

};

The Heap implementation will return a class derived from nvk::DeviceMemory

Derived class keeps reference to Heap

Destructor knows how to free the memory

4/4/2016

Page 35: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

35

NVKResource Tracking GPU

4/4/2016

Bind

Buffer

Bind

BufferDraw

Bind

Desc…

CommandBuffer Queue

Submit

GPU

Process

Set of resources

keep alive as long as it is use by CmdBuffer or GPU

Page 36: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

36

NVKResource Tracking GPU

4/4/2016

class ResourceTracker {

// track resources, increase refcount

void track(std::shared_ptr<vk::Buffer> const & buffer);

// Give Fence to tracker which can be checked if resources are still being used

void addFence(std::shared_ptr<vk::Fence> const & fence);

// check if any tracked resource used on GPU,

bool isUsed() const;

// decrease refcount of resources if not used anymore

void releaseUnused();

};

Introduce ResourceTracker Interface

Page 37: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

37

NVKResource Tracking GPU

Might be costly to track all used resources

Put each resource once in list results in small list, but slow insertion

Put each resource in list on each usage results large list, but fast insertion

Use ResourceTracker as template interface for CommandBuffer

Build up list once and keep it over multiple frames

In debug mode check if all resources are tracked

Should be nearly free in this mode4/4/2016

Page 38: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

38

NVK + VKCPPResults

4/4/2016

VKCPP for the ninja provides modern C+11 API for

Reduced code complexity

Improved compile time error checking

NVK provides

RAII styles gives exception safety

Refcounting provides resource tracking on CPU

Resource tracker provides resource tracking on GPU

Hello Vulkan in NVK needs only about 200 lines of code

Page 39: VKCPP - on-demand.gputechconf.comon-demand.gputechconf.com/gtc/2016/presentation/s6133-markus-t… · April 4-7, 2016 | Silicon Valley Markus Tavenrath Senior Developer Technology

April 4-7, 2016 | Silicon Valley

THANK YOU

Get it now: https://github.com/nvpro-pipeline/vkcpp


Recommended