Tag: libraries

Entries for tag "libraries", ordered from most recent. Entry count: 34.

Pages: 1 2 3 ... 5 >

# Debugging D3D12 driver crash

Wed
12
Sep 2018

New generation, explcit graphics APIs (Vulkan and DirectX 12) are more efficient, involve less CPU overhead. Part of it is that they don't check most errors. In old APIs (Direct3D 9, OpenGL) every function call was validated internally, returned success of failure code, while driver crash indicated a bug in driver code. New APIs, on the other hand, rely on developer doing the right thing. Of course, some functions still return error code (especially ones that allocate memory or create some resource), but those that record commands into a command list just return void. If you do something illegal, you can expect undefined behavior. You can use Validation Layers / Debug Layer to do some checks, but otherwise everything may work fine on some GPUs, you may get incorrect result, or you may experience driver crash or timeout (called "TDR"). Good thing is that (contrary to old Windows XP), crash inside graphics driver doesn't cause "blue screen of death" or machine restart. System just restarts graphics hardware and driver, while your program receives DXGI_ERROR_DEVICE_REMOVED code from one of functions like IDXGISwapChain::​Present. Unfortunately, you then don't know which specific draw call or other command caused the crash.

NVIDIA proposed solution for that: they created NVIDIA Aftermath library. It lets you (among other things) record commands that write custom "marker" data to a buffer that survives driver crash, so you can later read it and see which command was successfully executed last. Unfortunately, this library works only with NVIDIA graphics cards.

Some time ago I showed a portable solution for Vulkan in my post: "Debugging Vulkan driver crash - equivalent of NVIDIA Aftermath". Now I'd like to present a solution for Direct3D 12. It turns out that this API also provides a standardized way to achieve this, in form of a method ID3D12GraphicsCommandList2::​WriteBufferImmediate. One caveat: This new version of the interface requires:

I created a simple library that implements all the required logic under easy interface, which I called D3d12AfterCrash. You can find all the details and instruction for how to use it in file "D3d12AfterCrash.h".

I guess it would be better to allocate the buffer using WinAPI function VirtualAlloc(NULL, bufferSize, MEM_COMMIT, PAGE_READWRITE), then call ID3D12Device3::​OpenExistingHeapFromAddress and ID3D12Device::​CreatePlacedResource, but my simple way of just doing ID3D12Device::​CreateCommittedResource seems to work - buffer survives driver crash and preserves its content. I checked it on AMD as well as NVIDIA card.

Comments | #directx #graphics #libraries #productions Share

# Vulkan Memory Allocator 2.1.0

Tue
28
Aug 2018

Yesterday I merged changes in the code of Vulkan Memory Allocator that I've been working on for past few months to "master" branch, which I consider a major milestone, so I marked it as version 2.1.0-beta.1. There are many new features, including:

The release also includes many smaller bug fixes, improvements and additions. Everything is tested and documented. Yet I call it "beta" version, to encourage you to test it in your project and send me your feedback.

Comments | #vulkan #libraries #productions #graphics Share

# str_view - null-termination-aware string-view class for C++

Sun
19
Aug 2018

tl;dr I've written a small library, which I called "str_view - null-termination-aware string-view class for C++". You can find code and documentation on GitHub - sawickiap/str_view. Read on to see full story behind it...

Let me disclose my controversial beliefs: I like C++ STL. I think that any programming language needs to provide some built-in strings and containers to be called modern and suitable for developing large programs. But of course I'm aware that careless use of classes like std::list or std::map makes program very slow due to large number of dynamic allocations.

What I value the most is RAII - the concept that memory is automatically freed whenever an object referenced by value is destroyed. That's why I use std::unique_ptr all over the place in my personal code. Whenever I create and own an array, I use std::vector, but when I just pass it to some other code for reading, I pass raw pointer and number of elements - myVec.data() and myVec.size(). Similarly, whenever I own and build a string, I use std::string (or rather std::wstring - I like Unicode), but when I pass it somewhere for reading, I use raw pointer.

There are multiple ways a string can be passed. One is pointer to first character and number of characters. Another one is pointer to first character and pointer to the next after last character - a pair of iterators, also called range. These two can be trivially converted between each other. Out of these, I prefer pointer + length, because I think that number of characters is slightly more often needed than pointer past the end.

But there is another way of passing strings common in C and C++ programs - just one pointer to a string that needs to be null-terminated. I think that null-terminated strings is one of the worst and the most stupid inventions in computer science. Not only it limits set of characters available to be used in string content by excluding '\0', but it also makes calculation of string length O(n) time complexity. It also creates opportunity for security bugs. Still we have to deal with it because that's the format that most libraries expect.

I came up with an idea for a class that would encapsulate a reference to an externally-owned, immutable string, or a piece of thereof. Objects of such class could be used to pass strings to library functions instead of e.g. a pointer to null-terminated string or a pair of iterators. They can be then queried for length(), indexed to access individual characters etc., as well as asked for a null-terminated copy using c_str() method - similar to std::string.

Code like this already exists, e.g. C++17 introduces class std::string_view. But my implementation has a twist that I'm quite happy with, which made me call my class "null-termination-aware". My str_view class not only remembers pointer and length of the referred string, but also the way it was created to avoid unnecessary operations and lazily evaluate those that are requested.

If you consider such class useful in your C++ code, see GitHub - sawickiap/str_view project for code (it's just a single header file), documentation, and extensive set of tests. I share this code for free, on MIT license. Feel free to contact me if you find any bugs or have any suggestions regarding this library.

Comments | #productions #libraries #c++ Share

# Human-friendly classification of Vulkan resources

Wed
06
Jun 2018

In graphics programming we deal with different kinds of resources. Their specific types and names depend on graphics API. For example, in Direct3D 9 we have vertex buffers, index buffers, constant buffers, textures etc. OpenGL equivalent of constant buffer is uniform buffer object (UBO).

Vulkan has only two types of resources: buffers and images. This may be the only thing that is simpler in Vulkan than in other APIs :) When creating such resource, we specify usage flags that define how do we intend to use it. For example, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT means that a buffer may be used as vertex buffer. VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT means that an image may be used as color attachment (which is Vulkan name for “render target”).

Such flags may be combined together, so a single buffer can contain data to be used as vertex buffer, index buffer, and uniform buffer. I’m not 100% sure if this is guaranteed by the specification (theoretically some drivers could return disjoint sets of VkMemoryRequirements::memoryTypeBits for different usage flags), but I think that every real implementation allows that. It means we cannot clearly classify buffers and images into categories. Despite that, I decided to develop a human-friendly classification of Vulkan resources into several categories, starting from most “special”, and ending with most “common/generic” ones. I propose following algorithm:

For buffers:
  // Buffer is used as source of data for fixed-function stage of graphics pipeline.
  // It’s indirect, vertex, or index buffer.
  if ((usage & (VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT |
    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
    VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) != 0)
    return class0;
  // Buffer is accessed by shaders for load/store/atomic.
  // Aka “UAV”
  else if ((usage & (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) != 0)
    return class1;
  // Buffer is accessed by shaders for reading uniform data.
  // Aka “constant buffer”
  else if ((usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) != 0)
    return class2;
  // Any other type of buffer.
  // Notice that VK_BUFFER_USAGE_TRANSFER_SRC_BIT and VK_BUFFER_USAGE_TRANSFER_DST_BIT
  // flags are intentionally ignored.
  else
    return class3;

For images:
  // Image is used as depth/stencil “texture/surface”.
  if ((usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
    return class0;
  // Image is used as other type of attachment.
  // Aka “render target”
  else if ((usage & (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) != 0)
    return class1;
  // Image is accessed by shaders for sampling.
  // Aka “texture”
  else if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0)
    return class2;
  // Any other type of image.
  // Notice that VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_TRANSFER_DST_BIT
  // flags are intentionally ignored.
  else
    return class3;

I needed this because I wanted to introduce better coloring to VMA Dump Vis. Vulkan Memory Allocator (VMA) is a C++ library that simplifies GPU memory management in Vulkan applications. VMA Dump Vis is a Python script that can visualize JSON dump from this library on a picture. As I updated the library to remember usage flags of created resources, I wanted to use them to show more information on the picture. To do this, I defined following color scheme:

Example visualization of Vulkan memory in some game:

This color scheme is carefully designed. I based it on following principles:

  1. Brightness: Details too small to be shown as filled rectangles are black. Borders of rectangles representing allocations are dark gray. Fill colors of all allocations must be visually brighter than this.
  2. Saturation: Memory of unknown purpose (small details, free space, allocation of unknown type) is black/gray. Allocations of known type have specific color. Additionally, buffers and images with no special usage flags use more desaturated (brighter) color.
  3. Warm/cool colors: Buffers use warm colors: red, orange, yellow. Images use cool colors: purple, blue etc.
  4. Hue (1): Classes of buffers, from most special to most generic, use colors from red, through orange, to yellow. Classes of images, from most special to most generic, use colors from purple, through violet, to cyan.
  5. Hue (2): Vulkan images with VK_IMAGE_TILING_OPTIMAL should be used wherever possible, so those with VK_IMAGE_TILING_LINEAR are just marked with green. Images of unknown tiling have color between cyan and green.

You can already visualize your Vulkan memory with all these colors if you grab Vulkan Memory Allocator from development branch. I think that this classification of GPU resources and accompanying color scheme could also be useful for other graphics APIs.

Comments | #vulkan #libraries #productions Share

# Debugging Vulkan driver crash - equivalent of NVIDIA Aftermath

Wed
28
Mar 2018

New generation, explcit graphics APIs (Vulkan and DirectX 12) are more efficient, involve less CPU overhead. Part of it is that they don't check most errors. In old APIs (Direct3D 9, OpenGL) every function call was validated internally, returned success of failure code, while driver crash indicated a bug in driver code. New APIs, on the other hand, rely on developer doing the right thing. Of course some functions still return error code (especially ones that allocate memory or create some resource), but those that record commands into a command buffer just return void. If you do something illegal, you can expect undefined behavior. You can use Validation Layers / Debug Layer to do some checks, but otherwise everything may work fine on some GPUs, you may get incorrect result, or you may experience driver crash or timeout (called "TDR"). Good thing is that (contrary to old Windows XP), crash inside graphics driver doesn't cause "blue screen of death" or machine restart. System just restarts graphics hardware and driver, while your program receives VK_ERROR_DEVICE_LOST code from one of functions like vkQueueSubmit. Unfortunately, you then don't know which specific draw call or other command caused the crash.

NVIDIA proposed solution for that: they created NVIDIA Aftermath library. It lets you (among other things) record commands that write custom "marker" data to a buffer that survives driver crash, so you can later read it and see which command was successfully executed last. Unfortunately, this library works only with NVIDIA graphics cards and only in D3D11 and D3D12.

I was looking for similar solution for Vulkan. When I saw that Vulkan can "import" external memory, I thought that maybe I could use function vkCmdFillBuffer to write immediate value to such buffer and this way implement the same logic. I then started experimenting with extensions: VK_KHR_get_physical_device_properties_2, VK_KHR_external_memory_capabilities, VK_KHR_external_memory, VK_KHR_external_memory_win32, VK_KHR_dedicated_allocation. I was basically trying to somehow allocate a piece of system memory and import it to Vulkan to write to it as Vulkan buffer. I tried many things: CreateFileMapping + MapViewOfFile, HeapCreate + HeapAlloc and other ways, with various flags, but nothing worked for me. I also couldn't find any description or sample code of how these extensions could be used in Windows to import some system memory as Vulkan buffer.

Everything changed when I learned that creating normal device memory and buffer inside Vulkan is enough! It survives driver crash, so its content can be read later via mapped pointer. No extensions required. I don't think this is guaranteed by specification, but it seems to work on both AMD and NVIDIA cards. So my current solution to write makers that survive driver crash in Vulkan is:

  1. Call vkAllocateMemory to allocate VkDeviceMemory from memory type that has HOST_VISIBLE + HOST_COHERENT flags. (This is system RAM. Spec guarantees that you can always find such type.)
  2. Map the memory using vkMapMemory to get raw CPU pointer to its data.
  3. Call vkCreateBuffer to create VkBuffer with VK_BUFFER_USAGE_TRANSFER_DST_BIT and bind it to that memory using vkBindBufferMemory.
  4. While recording commands to VkCommandBuffer, use vkCmdFillBuffer to write immediate data with your custom "markers" to the buffer.
  5. If everything goes right, don't forget to vkDestroyBuffer and vkFreeMemory during shutdown.
  6. If you experience driver crash (receive VK_ERROR_DEVICE_LOST), read data under the pointer to see what marker values were successfully written last and deduce which one of your commands might cause the crash.

There is also a new extension available on latest AMD drivers: VK_AMD_buffer_marker. It adds just one function: vkCmdWriteBufferMarkerAMD. It works similar to beforementioned vkCmdFillBuffer, but it adds two good things that let you write your markers with much better granularity:

I created a simple library that implements all this logic under easy interface, which I called "Vulkan AfterCrash". All you need to use it is just this single file: VulkanAfterCrash.h.

Update 4 April 2018: In GDC 2018 talk "Aftermath: Advances in GPU Crash Debugging (Presented by NVIDIA)", Alex Dunn announced that a Vulkan extension from NVIDIA will also be available, called VK_NV_device_diagnostic_checkpoints, but I can see it's not publicly accessible yet.

Update 1 August 2018: Documentation for extension VK_NV_device_diagnostic_checkpoints has been published in Vulkan version 1.1.82.

Update 12 September 2018: I've created similar, portable library for Direct3D 12 - see blog post "Debugging D3D12 driver crash".

Comments | #vulkan #graphics #libraries #productions Share

# Vulkan Memory Allocator 2.0.0

Mon
26
Mar 2018

At Game Developers Conference (GDC) last week I released final version 2.0.0 of Vulkan Memory Allocator library. It is now well documented and thanks to contributions from open source community it compiles and works on Windows, Linux, Android, and MacOS. Together with it I released VMA Dump Vis - a Python script that visualizes Vulkan memory on a picture. From now on I will continue incremental development on "development" branch and occasionally merge to "master". Feel free to contact me if you have any feedback, suggestions or if you find a bug.

Comments | #vulkan #libraries #productions #graphics Share

# Vulkan Memory Allocator 2.0.0-alpha.3

Wed
13
Sep 2017

I just published new version of Vulkan Memory Allocator 2.0.0-alpha.3. I'm quite happy with the quality of this code. Documentation is also updated, so if nothing else, please just go see User guide. I still marked it as "alpha" because I would like to ask for feedback and I may still change everything.

I would like to discuss proposed terminology. Naming things in code is a hard problem in general, and especially as English is not my native language, so please fill free to contact me and propose more elegant names to what I called: allocator, allocation, pool, block, stats, free range, used/unused bytes, own memory, persistently mapped memory, pointer to mapped data, lost allocation (becoming lost, making other lost), defragmentation, and used internally: suballocation, block vector.

Comments | #vulkan #productions #libraries #graphics Share

# RegScript 2 - Parameters Framework

Sun
03
Apr 2016

On April 1st I've read a very interesting blog post that doesn't seem like April Fools' joke: Game Development Needs Data Pipeline Middleware. I fully agree with the author. There is a code very much needed in every game engine, game editor and other graphics/music/media applications, written over and over again - the one about storing, editing and serializing data structures of various kinds (basically all objects that make up the state/document/game level of a program), each having a set of parameters of various types (integers, floats, strings, vectors, arrays etc.) - so it makes sense to create a library for it.

I (as probably every game developer) already tried to create such framework many times. Now I decided to share the source of my last attempt: RegScript2 @ GitHub. It is not finished and some design decisions I've made may seem controversial, but at least we could start discussion about the solution. What do you think about it? Feel free to e-mail me at sawickiap__REMOVE__@poczta.onet.pl, comment this post or read and interact with my code on GitHub.

Comments | #libraries Share

Pages: 1 2 3 ... 5 >

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2018