yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
6.6 KiB211 linesraw
1// vk-buffer.cpp
2#include "vk-buffer.h"
3
4#include "vk-util.h"
5#if SLANG_WINDOWS_FAMILY
6#include <dxgi1_2.h>
7#endif
8
9namespace gfx
10{
11
12using namespace Slang;
13
14namespace vk
15{
16
17Result VKBufferHandleRAII::init(
18    const VulkanApi& api,
19    Size bufferSize,
20    VkBufferUsageFlags usage,
21    VkMemoryPropertyFlags reqMemoryProperties,
22    bool isShared,
23    VkExternalMemoryHandleTypeFlagsKHR extMemHandleType)
24{
25    assert(!isInitialized());
26
27    m_api = &api;
28    m_memory = VK_NULL_HANDLE;
29    m_buffer = VK_NULL_HANDLE;
30
31    VkBufferCreateInfo bufferCreateInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
32    bufferCreateInfo.size = bufferSize;
33    bufferCreateInfo.usage = usage;
34    bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
35
36    VkExternalMemoryBufferCreateInfo externalMemoryBufferCreateInfo = {
37        VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO};
38    if (isShared)
39    {
40        externalMemoryBufferCreateInfo.handleTypes = extMemHandleType;
41        bufferCreateInfo.pNext = &externalMemoryBufferCreateInfo;
42    }
43
44    SLANG_VK_RETURN_ON_FAIL(
45        api.vkCreateBuffer(api.m_device, &bufferCreateInfo, nullptr, &m_buffer));
46
47    VkMemoryRequirements memoryReqs = {};
48    api.vkGetBufferMemoryRequirements(api.m_device, m_buffer, &memoryReqs);
49
50    int memoryTypeIndex = api.findMemoryTypeIndex(memoryReqs.memoryTypeBits, reqMemoryProperties);
51    assert(memoryTypeIndex >= 0);
52
53    VkMemoryPropertyFlags actualMemoryProperites =
54        api.m_deviceMemoryProperties.memoryTypes[memoryTypeIndex].propertyFlags;
55    VkMemoryAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
56    allocateInfo.allocationSize = memoryReqs.size;
57    allocateInfo.memoryTypeIndex = memoryTypeIndex;
58#if SLANG_WINDOWS_FAMILY
59    VkExportMemoryWin32HandleInfoKHR exportMemoryWin32HandleInfo = {
60        VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR};
61#endif
62    VkExportMemoryAllocateInfoKHR exportMemoryAllocateInfo = {
63        VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR};
64    if (isShared)
65    {
66#if SLANG_WINDOWS_FAMILY
67        exportMemoryWin32HandleInfo.pNext = nullptr;
68        exportMemoryWin32HandleInfo.pAttributes = nullptr;
69        exportMemoryWin32HandleInfo.dwAccess =
70            DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
71        exportMemoryWin32HandleInfo.name = NULL;
72
73        exportMemoryAllocateInfo.pNext =
74            extMemHandleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
75                ? &exportMemoryWin32HandleInfo
76                : nullptr;
77#endif
78        exportMemoryAllocateInfo.handleTypes = extMemHandleType;
79        allocateInfo.pNext = &exportMemoryAllocateInfo;
80    }
81    VkMemoryAllocateFlagsInfo flagInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO};
82    if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
83    {
84        flagInfo.deviceMask = 1;
85        flagInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
86
87        flagInfo.pNext = allocateInfo.pNext;
88        allocateInfo.pNext = &flagInfo;
89    }
90
91    SLANG_VK_RETURN_ON_FAIL(api.vkAllocateMemory(api.m_device, &allocateInfo, nullptr, &m_memory));
92    SLANG_VK_RETURN_ON_FAIL(api.vkBindBufferMemory(api.m_device, m_buffer, m_memory, 0));
93
94    return SLANG_OK;
95}
96
97BufferResourceImpl::BufferResourceImpl(const IBufferResource::Desc& desc, DeviceImpl* renderer)
98    : Parent(desc), m_renderer(renderer)
99{
100    assert(renderer);
101}
102
103BufferResourceImpl::~BufferResourceImpl()
104{
105    if (sharedHandle.handleValue != 0)
106    {
107#if SLANG_WINDOWS_FAMILY
108        CloseHandle((HANDLE)sharedHandle.handleValue);
109#endif
110    }
111}
112
113DeviceAddress BufferResourceImpl::getDeviceAddress()
114{
115    if (!m_buffer.m_api->vkGetBufferDeviceAddress)
116        return 0;
117    VkBufferDeviceAddressInfo info = {};
118    info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
119    info.buffer = m_buffer.m_buffer;
120    return (DeviceAddress)m_buffer.m_api->vkGetBufferDeviceAddress(m_buffer.m_api->m_device, &info);
121}
122
123Result BufferResourceImpl::getNativeResourceHandle(InteropHandle* outHandle)
124{
125    outHandle->handleValue = (uint64_t)m_buffer.m_buffer;
126    outHandle->api = InteropHandleAPI::Vulkan;
127    return SLANG_OK;
128}
129
130Result BufferResourceImpl::getSharedHandle(InteropHandle* outHandle)
131{
132    // Check if a shared handle already exists for this resource.
133    if (sharedHandle.handleValue != 0)
134    {
135        *outHandle = sharedHandle;
136        return SLANG_OK;
137    }
138
139    // If a shared handle doesn't exist, create one and store it.
140#if SLANG_WINDOWS_FAMILY
141    VkMemoryGetWin32HandleInfoKHR info = {};
142    info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
143    info.pNext = nullptr;
144    info.memory = m_buffer.m_memory;
145    info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
146
147    auto api = m_buffer.m_api;
148    PFN_vkGetMemoryWin32HandleKHR vkCreateSharedHandle;
149    vkCreateSharedHandle = api->vkGetMemoryWin32HandleKHR;
150    if (!vkCreateSharedHandle)
151    {
152        return SLANG_FAIL;
153    }
154    SLANG_VK_RETURN_ON_FAIL(
155        vkCreateSharedHandle(api->m_device, &info, (HANDLE*)&outHandle->handleValue));
156#else
157    VkMemoryGetFdInfoKHR info = {};
158    info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
159    info.pNext = nullptr;
160    info.memory = m_buffer.m_memory;
161    info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
162
163    auto api = m_buffer.m_api;
164    PFN_vkGetMemoryFdKHR vkCreateSharedHandle;
165    vkCreateSharedHandle = api->vkGetMemoryFdKHR;
166    if (!vkCreateSharedHandle)
167    {
168        return SLANG_FAIL;
169    }
170    SLANG_VK_RETURN_ON_FAIL(
171        vkCreateSharedHandle(api->m_device, &info, (int*)&outHandle->handleValue));
172#endif
173    outHandle->api = InteropHandleAPI::Vulkan;
174    return SLANG_OK;
175}
176
177Result BufferResourceImpl::map(MemoryRange* rangeToRead, void** outPointer)
178{
179    SLANG_UNUSED(rangeToRead);
180    auto api = m_buffer.m_api;
181    SLANG_VK_RETURN_ON_FAIL(
182        api->vkMapMemory(api->m_device, m_buffer.m_memory, 0, VK_WHOLE_SIZE, 0, outPointer));
183    return SLANG_OK;
184}
185
186Result BufferResourceImpl::unmap(MemoryRange* writtenRange)
187{
188    SLANG_UNUSED(writtenRange);
189    auto api = m_buffer.m_api;
190    api->vkUnmapMemory(api->m_device, m_buffer.m_memory);
191    return SLANG_OK;
192}
193
194Result BufferResourceImpl::setDebugName(const char* name)
195{
196    Parent::setDebugName(name);
197    auto api = m_buffer.m_api;
198    if (api->vkDebugMarkerSetObjectNameEXT)
199    {
200        VkDebugMarkerObjectNameInfoEXT nameDesc = {};
201        nameDesc.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
202        nameDesc.object = (uint64_t)m_buffer.m_buffer;
203        nameDesc.objectType = VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
204        nameDesc.pObjectName = name;
205        api->vkDebugMarkerSetObjectNameEXT(api->m_device, &nameDesc);
206    }
207    return SLANG_OK;
208}
209
210} // namespace vk
211} // namespace gfx