Skip to content

Commit 3210b43

Browse files
committed
[hgiVulkan] Add support for VK_EXT_host_image_copy
1 parent a7c0637 commit 3210b43

File tree

10 files changed

+388
-203
lines changed

10 files changed

+388
-203
lines changed

pxr/imaging/hgiVulkan/blitCmds.cpp

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,8 @@ HgiVulkanBlitCmds::CopyTextureGpuToCpu(
143143
const VkImageLayout oldLayout = srcTexture->GetImageLayout();
144144
const auto [srcAccess, srcStage] =
145145
_GetOldAccessAndPipelineStageFlags(oldLayout);
146-
HgiVulkanTexture::TransitionImageBarrier(
146+
srcTexture->LayoutBarrier(
147147
_commandBuffer,
148-
srcTexture,
149148
oldLayout,
150149
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // transition tex to this layout
151150
srcAccess,
@@ -172,9 +171,8 @@ HgiVulkanBlitCmds::CopyTextureGpuToCpu(
172171
// Transition image back to what it was.
173172
VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
174173
srcTexture->GetDescriptor().usage);
175-
HgiVulkanTexture::TransitionImageBarrier(
174+
srcTexture->LayoutBarrier(
176175
_commandBuffer,
177-
srcTexture,
178176
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
179177
oldLayout, // transition tex to this layout
180178
HgiVulkanTexture::NO_PENDING_WRITES, // no pending writes
@@ -338,9 +336,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
338336
const VkImageLayout oldLayoutSrc = srcTexture->GetImageLayout();
339337
const auto [srcAccessSrc, srcStageSrc] =
340338
_GetOldAccessAndPipelineStageFlags(oldLayoutSrc);
341-
HgiVulkanTexture::TransitionImageBarrier(
339+
srcTexture->LayoutBarrier(
342340
_commandBuffer,
343-
srcTexture,
344341
oldLayoutSrc,
345342
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
346343
srcAccessSrc,
@@ -352,9 +349,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
352349
const VkImageLayout oldLayoutDst = dstTexture->GetImageLayout();
353350
const auto [srcAccessDst, srcStageDst] =
354351
_GetOldAccessAndPipelineStageFlags(oldLayoutDst);
355-
HgiVulkanTexture::TransitionImageBarrier(
352+
dstTexture->LayoutBarrier(
356353
_commandBuffer,
357-
dstTexture,
358354
oldLayoutDst,
359355
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
360356
srcAccessDst,
@@ -374,9 +370,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
374370
// Transition src image back to what it was.
375371
const VkAccessFlags accessSrc = HgiVulkanTexture::GetDefaultAccessFlags(
376372
srcTexture->GetDescriptor().usage);
377-
HgiVulkanTexture::TransitionImageBarrier(
373+
srcTexture->LayoutBarrier(
378374
_commandBuffer,
379-
srcTexture,
380375
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
381376
oldLayoutSrc,
382377
HgiVulkanTexture::NO_PENDING_WRITES,
@@ -387,9 +382,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
387382
// Transition dst image back to what it was.
388383
const VkAccessFlags accessDst = HgiVulkanTexture::GetDefaultAccessFlags(
389384
dstTexture->GetDescriptor().usage);
390-
HgiVulkanTexture::TransitionImageBarrier(
385+
dstTexture->LayoutBarrier(
391386
_commandBuffer,
392-
dstTexture,
393387
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
394388
oldLayoutDst,
395389
VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -545,9 +539,8 @@ HgiVulkanBlitCmds::CopyTextureToBuffer(HgiTextureToBufferOp const& copyOp)
545539
VkImageLayout oldLayout = srcTexture->GetImageLayout();
546540
const auto [srcAccess, srcStage] =
547541
_GetOldAccessAndPipelineStageFlags(oldLayout);
548-
HgiVulkanTexture::TransitionImageBarrier(
542+
srcTexture->LayoutBarrier(
549543
_commandBuffer,
550-
srcTexture,
551544
/*oldLayout*/oldLayout,
552545
/*newLayout*/VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
553546
/*producerAccess*/srcAccess,
@@ -592,9 +585,8 @@ HgiVulkanBlitCmds::CopyTextureToBuffer(HgiTextureToBufferOp const& copyOp)
592585
// Transition image layout back to original layout.
593586
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
594587
srcTexture->GetDescriptor().usage);
595-
HgiVulkanTexture::TransitionImageBarrier(
588+
srcTexture->LayoutBarrier(
596589
_commandBuffer,
597-
srcTexture,
598590
/*oldLayout*/VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
599591
/*newLayout*/oldLayout,
600592
/*producerAccess*/VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -634,9 +626,8 @@ HgiVulkanBlitCmds::CopyBufferToTexture(HgiBufferToTextureOp const& copyOp)
634626
VkImageLayout oldLayout = dstTexture->GetImageLayout();
635627
const auto [srcAccess, srcStage] =
636628
_GetOldAccessAndPipelineStageFlags(oldLayout);
637-
HgiVulkanTexture::TransitionImageBarrier(
629+
dstTexture->LayoutBarrier(
638630
_commandBuffer,
639-
dstTexture,
640631
/*oldLayout*/oldLayout,
641632
/*newLayout*/VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
642633
/*producerAccess*/srcAccess,
@@ -680,9 +671,8 @@ HgiVulkanBlitCmds::CopyBufferToTexture(HgiBufferToTextureOp const& copyOp)
680671
// Transition image layout back to original layout.
681672
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
682673
dstTexture->GetDescriptor().usage);
683-
HgiVulkanTexture::TransitionImageBarrier(
674+
dstTexture->LayoutBarrier(
684675
_commandBuffer,
685-
dstTexture,
686676
/*oldLayout*/VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
687677
/*newLayout*/oldLayout,
688678
/*producerAccess*/VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -726,9 +716,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
726716
const VkImageLayout oldLayout = vkTex->GetImageLayout();
727717
const auto [srcAccess, srcStage] =
728718
_GetOldAccessAndPipelineStageFlags(oldLayout);
729-
HgiVulkanTexture::TransitionImageBarrier(
719+
vkTex->LayoutBarrier(
730720
_commandBuffer,
731-
vkTex,
732721
oldLayout,
733722
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
734723
srcAccess,
@@ -758,9 +747,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
758747
imageBlit.dstOffsets[1].z = 1;
759748

760749
// Transition current mip level to image blit destination
761-
HgiVulkanTexture::TransitionImageBarrier(
750+
vkTex->LayoutBarrier(
762751
_commandBuffer,
763-
vkTex,
764752
oldLayout,
765753
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
766754
srcAccess,
@@ -781,9 +769,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
781769
VK_FILTER_LINEAR);
782770

783771
// Prepare current mip level as image blit source for next level
784-
HgiVulkanTexture::TransitionImageBarrier(
772+
vkTex->LayoutBarrier(
785773
_commandBuffer,
786-
vkTex,
787774
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
788775
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
789776
VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -796,9 +783,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
796783
// Return all mips from TRANSFER_SRC to their original layout
797784
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
798785
vkTex->GetDescriptor().usage);
799-
HgiVulkanTexture::TransitionImageBarrier(
786+
vkTex->LayoutBarrier(
800787
_commandBuffer,
801-
vkTex,
802788
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
803789
oldLayout,
804790
VK_ACCESS_TRANSFER_READ_BIT,

pxr/imaging/hgiVulkan/capabilities.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ TF_DEFINE_ENV_SETTING(HGIVULKAN_ENABLE_UMA, true,
2727
"Use Vulkan with UMA (if device supports)");
2828
TF_DEFINE_ENV_SETTING(HGIVULKAN_ENABLE_REBAR, false,
2929
"Use Vulkan with ReBAR (if device supports)");
30+
TF_DEFINE_ENV_SETTING(HGIVULKAN_ENABLE_HOST_IMAGE_COPY, true,
31+
"Use Vulkan direct image copy from host");
3032

3133
static void _DumpDeviceDeviceMemoryProperties(
3234
const VkPhysicalDeviceMemoryProperties& vkMemoryProperties)
@@ -181,6 +183,19 @@ HgiVulkanCapabilities::HgiVulkanCapabilities(HgiVulkanDevice* device)
181183
vkPhysicalDeviceIdProperties.pNext = vkDeviceProperties2.pNext;
182184
vkDeviceProperties2.pNext = &vkPhysicalDeviceIdProperties;
183185

186+
// Host image copy feature
187+
const bool hostImageCopyExtAvailable =
188+
TfGetEnvSetting(HGIVULKAN_ENABLE_HOST_IMAGE_COPY) &&
189+
device->IsSupportedExtension(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME);
190+
if (hostImageCopyExtAvailable) {
191+
vkHostImageCopyProperties.sType =
192+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT;
193+
vkHostImageCopyProperties.pNext = vkDeviceProperties2.pNext;
194+
vkHostImageCopyProperties.pCopyDstLayouts = vkHostImageCopyDstLayouts.data();
195+
vkHostImageCopyProperties.copyDstLayoutCount = vkHostImageCopyDstLayouts.size();
196+
vkDeviceProperties2.pNext = &vkHostImageCopyProperties;
197+
}
198+
184199
// Query device properties
185200
vkGetPhysicalDeviceProperties2(physicalDevice, &vkDeviceProperties2);
186201
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &vkMemoryProperties);
@@ -223,7 +238,7 @@ HgiVulkanCapabilities::HgiVulkanCapabilities(HgiVulkanDevice* device)
223238
vkVertexAttributeDivisorFeatures.pNext = vkDeviceFeatures2.pNext;
224239
vkDeviceFeatures2.pNext = &vkVertexAttributeDivisorFeatures;
225240

226-
// Barycentric features
241+
// Barycentric feature
227242
const bool barycentricExtSupported = device->IsSupportedExtension(
228243
VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
229244
if (barycentricExtSupported) {
@@ -232,8 +247,8 @@ HgiVulkanCapabilities::HgiVulkanCapabilities(HgiVulkanDevice* device)
232247
vkBarycentricFeatures.pNext = vkDeviceFeatures2.pNext;
233248
vkDeviceFeatures2.pNext = &vkBarycentricFeatures;
234249
}
235-
236-
// Line rasterization features
250+
251+
// Line rasterization feature
237252
const bool lineRasterizationExtSupported = device->IsSupportedExtension(
238253
VK_KHR_LINE_RASTERIZATION_EXTENSION_NAME);
239254
if (lineRasterizationExtSupported) {
@@ -243,6 +258,14 @@ HgiVulkanCapabilities::HgiVulkanCapabilities(HgiVulkanDevice* device)
243258
vkDeviceFeatures2.pNext = &vkLineRasterizationFeatures;
244259
}
245260

261+
// Host image copy feature
262+
if (hostImageCopyExtAvailable) {
263+
vkHostImageCopyFeatures.sType =
264+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT;
265+
vkHostImageCopyFeatures.pNext = vkDeviceFeatures2.pNext;
266+
vkDeviceFeatures2.pNext = &vkHostImageCopyFeatures;
267+
}
268+
246269
// Query device features
247270
vkGetPhysicalDeviceFeatures2(physicalDevice, &vkDeviceFeatures2);
248271

pxr/imaging/hgiVulkan/capabilities.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "pxr/imaging/hgiVulkan/api.h"
1313
#include "pxr/imaging/hgiVulkan/vulkan.h"
1414

15+
#include <array>
1516

1617
PXR_NAMESPACE_OPEN_SCOPE
1718

@@ -41,10 +42,13 @@ class HgiVulkanCapabilities final : public HgiCapabilities
4142
bool supportsNativeInterop;
4243

4344
VkPhysicalDeviceProperties2 vkDeviceProperties2 {};
45+
VkPhysicalDeviceMemoryProperties vkMemoryProperties {};
46+
VkPhysicalDeviceIDProperties vkPhysicalDeviceIdProperties {};
4447
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT
4548
vkVertexAttributeDivisorProperties {};
46-
47-
VkPhysicalDeviceMemoryProperties vkMemoryProperties {};
49+
VkPhysicalDeviceHostImageCopyPropertiesEXT vkHostImageCopyProperties {};
50+
// Storage for VkPhysicalDeviceHostImageCopyProperties::pCopyDstLayouts
51+
std::array<VkImageLayout, 32> vkHostImageCopyDstLayouts {};
4852

4953
VkPhysicalDeviceFeatures2 vkDeviceFeatures2 {};
5054
VkPhysicalDeviceVulkan11Features vkVulkan11Features {};
@@ -53,8 +57,7 @@ class HgiVulkanCapabilities final : public HgiCapabilities
5357
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR
5458
vkBarycentricFeatures {};
5559
VkPhysicalDeviceLineRasterizationFeaturesKHR vkLineRasterizationFeatures {};
56-
57-
VkPhysicalDeviceIDProperties vkPhysicalDeviceIdProperties {};
60+
VkPhysicalDeviceHostImageCopyFeaturesEXT vkHostImageCopyFeatures {};
5861
};
5962

6063
PXR_NAMESPACE_CLOSE_SCOPE

pxr/imaging/hgiVulkan/conversions.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,14 @@ _TextureUsageTable[][2] =
125125
};
126126
static_assert(HgiTextureUsageCustomBitsBegin == 1 << 5, "");
127127

128-
static const uint32_t
129-
_FormatFeatureTable[][2] =
130-
{
131-
{HgiTextureUsageBitsColorTarget, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT},
132-
{HgiTextureUsageBitsDepthTarget, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
133-
{HgiTextureUsageBitsStencilTarget, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
134-
{HgiTextureUsageBitsShaderRead, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
135-
{HgiTextureUsageBitsShaderWrite, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT},
128+
static const uint64_t
129+
_FormatFeature2Table[][2] =
130+
{
131+
{HgiTextureUsageBitsColorTarget, VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT},
132+
{HgiTextureUsageBitsDepthTarget, VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT},
133+
{HgiTextureUsageBitsStencilTarget, VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT},
134+
{HgiTextureUsageBitsShaderRead, VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT},
135+
{HgiTextureUsageBitsShaderWrite, VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT},
136136
};
137137
static_assert(HgiTextureUsageCustomBitsBegin == 1 << 5, "");
138138

@@ -440,11 +440,11 @@ HgiVulkanConversions::GetTextureUsage(HgiTextureUsage tu)
440440
return vkFlags;
441441
}
442442

443-
VkFormatFeatureFlags
444-
HgiVulkanConversions::GetFormatFeature(HgiTextureUsage tu)
443+
VkFormatFeatureFlags2
444+
HgiVulkanConversions::GetFormatFeature2(HgiTextureUsage tu)
445445
{
446-
VkFormatFeatureFlags vkFlags = 0;
447-
for (const auto& f : _FormatFeatureTable) {
446+
VkFormatFeatureFlags2 vkFlags = 0;
447+
for (const auto& f : _FormatFeature2Table) {
448448
if (tu & f[0]) vkFlags |= f[1];
449449
}
450450

pxr/imaging/hgiVulkan/conversions.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class HgiVulkanConversions final
3737
static VkImageUsageFlags GetTextureUsage(HgiTextureUsage tu);
3838

3939
HGIVULKAN_API
40-
static VkFormatFeatureFlags GetFormatFeature(HgiTextureUsage tu);
40+
static VkFormatFeatureFlags2 GetFormatFeature2(HgiTextureUsage tu);
4141

4242
HGIVULKAN_API
4343
static VkAttachmentLoadOp GetLoadOp(HgiAttachmentLoadOp op);
@@ -107,4 +107,3 @@ class HgiVulkanConversions final
107107
PXR_NAMESPACE_CLOSE_SCOPE
108108

109109
#endif
110-

pxr/imaging/hgiVulkan/device.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ HgiVulkanDevice::HgiVulkanDevice(HgiVulkanInstance* instance)
114114
continue;
115115
}
116116

117-
if (props.apiVersion < VK_API_VERSION_1_0) continue;
117+
if (props.apiVersion < VK_API_VERSION_1_3) continue;
118118

119119
// Try to find a preferred device type. Until we find one, store the
120120
// first non-preferred device as fallback in case we never find a
@@ -264,6 +264,11 @@ HgiVulkanDevice::HgiVulkanDevice(HgiVulkanInstance* instance)
264264
extensions.push_back(VK_KHR_LINE_RASTERIZATION_EXTENSION_NAME);
265265
}
266266

267+
// Allow use of host image copy
268+
if (IsSupportedExtension(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME)) {
269+
extensions.push_back(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME);
270+
}
271+
267272
// This extension is needed to allow the viewport to be flipped in Y so that
268273
// shaders and vertex data can remain the same between opengl and vulkan.
269274
extensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
@@ -351,6 +356,16 @@ HgiVulkanDevice::HgiVulkanDevice(HgiVulkanInstance* instance)
351356
features2.pNext = &lineRasterFeatures;
352357
}
353358

359+
VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures {
360+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT
361+
};
362+
if (IsSupportedExtension(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME)) {
363+
hostImageCopyFeatures.hostImageCopy =
364+
_capabilities->vkHostImageCopyFeatures.hostImageCopy;
365+
hostImageCopyFeatures.pNext = features2.pNext;
366+
features2.pNext = &hostImageCopyFeatures;
367+
}
368+
354369
VkDeviceCreateInfo createInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
355370
createInfo.queueCreateInfoCount = 1;
356371
createInfo.pQueueCreateInfos = &queueInfo;
@@ -373,25 +388,32 @@ HgiVulkanDevice::HgiVulkanDevice(HgiVulkanInstance* instance)
373388
//
374389

375390
vkCreateRenderPass2KHR = (PFN_vkCreateRenderPass2KHR)
376-
vkGetDeviceProcAddr(_vkDevice, "vkCreateRenderPass2KHR");
391+
vkGetDeviceProcAddr(_vkDevice, "vkCreateRenderPass2KHR");
377392

378393
if (_capabilities->supportsNativeInterop) {
379394
#if defined(VK_USE_PLATFORM_WIN32_KHR)
380395
vkGetMemoryWin32HandleKHR = (PFN_vkGetMemoryWin32HandleKHR)
381-
vkGetDeviceProcAddr(_vkDevice, "vkGetMemoryWin32HandleKHR");
396+
vkGetDeviceProcAddr(_vkDevice, "vkGetMemoryWin32HandleKHR");
382397

383398
vkGetSemaphoreWin32HandleKHR = (PFN_vkGetSemaphoreWin32HandleKHR)
384-
vkGetDeviceProcAddr(_vkDevice, "vkGetSemaphoreWin32HandleKHR");
399+
vkGetDeviceProcAddr(_vkDevice, "vkGetSemaphoreWin32HandleKHR");
385400
#elif defined(VK_USE_PLATFORM_XLIB_KHR)
386401
vkGetMemoryFdKHR = (PFN_vkGetMemoryFdKHR)
387-
vkGetDeviceProcAddr(_vkDevice, "vkGetMemoryFdKHR");
402+
vkGetDeviceProcAddr(_vkDevice, "vkGetMemoryFdKHR");
388403

389404
vkGetSemaphoreFdKHR = (PFN_vkGetSemaphoreFdKHR)
390-
vkGetDeviceProcAddr(_vkDevice, "vkGetSemaphoreFdKHR");
405+
vkGetDeviceProcAddr(_vkDevice, "vkGetSemaphoreFdKHR");
391406
#elif defined(VK_USE_PLATFORM_METAL_EXT)
392407
#endif
393408
}
394409

410+
if (_capabilities->vkHostImageCopyFeatures.hostImageCopy) {
411+
vkTransitionImageLayoutEXT = (PFN_vkTransitionImageLayoutEXT)
412+
vkGetDeviceProcAddr(_vkDevice, "vkTransitionImageLayoutEXT");
413+
vkCopyMemoryToImageEXT = (PFN_vkCopyMemoryToImageEXT)
414+
vkGetDeviceProcAddr(_vkDevice, "vkCopyMemoryToImageEXT");
415+
}
416+
395417
//
396418
// Memory allocator
397419
//

0 commit comments

Comments
 (0)