Skip to content

Commit 8b8e727

Browse files
committed
[hgiVulkan] Add support for VK_EXT_host_image_copy
1 parent 5799c77 commit 8b8e727

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
@@ -142,9 +142,8 @@ HgiVulkanBlitCmds::CopyTextureGpuToCpu(
142142
const VkImageLayout oldLayout = srcTexture->GetImageLayout();
143143
const auto [srcAccess, srcStage] =
144144
_GetOldAccessAndPipelineStageFlags(oldLayout);
145-
HgiVulkanTexture::TransitionImageBarrier(
145+
srcTexture->LayoutBarrier(
146146
_commandBuffer,
147-
srcTexture,
148147
oldLayout,
149148
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // transition tex to this layout
150149
srcAccess,
@@ -171,9 +170,8 @@ HgiVulkanBlitCmds::CopyTextureGpuToCpu(
171170
// Transition image back to what it was.
172171
VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
173172
srcTexture->GetDescriptor().usage);
174-
HgiVulkanTexture::TransitionImageBarrier(
173+
srcTexture->LayoutBarrier(
175174
_commandBuffer,
176-
srcTexture,
177175
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
178176
oldLayout, // transition tex to this layout
179177
HgiVulkanTexture::NO_PENDING_WRITES, // no pending writes
@@ -337,9 +335,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
337335
const VkImageLayout oldLayoutSrc = srcTexture->GetImageLayout();
338336
const auto [srcAccessSrc, srcStageSrc] =
339337
_GetOldAccessAndPipelineStageFlags(oldLayoutSrc);
340-
HgiVulkanTexture::TransitionImageBarrier(
338+
srcTexture->LayoutBarrier(
341339
_commandBuffer,
342-
srcTexture,
343340
oldLayoutSrc,
344341
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
345342
srcAccessSrc,
@@ -351,9 +348,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
351348
const VkImageLayout oldLayoutDst = dstTexture->GetImageLayout();
352349
const auto [srcAccessDst, srcStageDst] =
353350
_GetOldAccessAndPipelineStageFlags(oldLayoutDst);
354-
HgiVulkanTexture::TransitionImageBarrier(
351+
dstTexture->LayoutBarrier(
355352
_commandBuffer,
356-
dstTexture,
357353
oldLayoutDst,
358354
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
359355
srcAccessDst,
@@ -373,9 +369,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
373369
// Transition src image back to what it was.
374370
const VkAccessFlags accessSrc = HgiVulkanTexture::GetDefaultAccessFlags(
375371
srcTexture->GetDescriptor().usage);
376-
HgiVulkanTexture::TransitionImageBarrier(
372+
srcTexture->LayoutBarrier(
377373
_commandBuffer,
378-
srcTexture,
379374
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
380375
oldLayoutSrc,
381376
HgiVulkanTexture::NO_PENDING_WRITES,
@@ -386,9 +381,8 @@ void HgiVulkanBlitCmds::BlitTexture(HgiTextureHandle src, HgiTextureHandle dst)
386381
// Transition dst image back to what it was.
387382
const VkAccessFlags accessDst = HgiVulkanTexture::GetDefaultAccessFlags(
388383
dstTexture->GetDescriptor().usage);
389-
HgiVulkanTexture::TransitionImageBarrier(
384+
dstTexture->LayoutBarrier(
390385
_commandBuffer,
391-
dstTexture,
392386
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
393387
oldLayoutDst,
394388
VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -536,9 +530,8 @@ HgiVulkanBlitCmds::CopyTextureToBuffer(HgiTextureToBufferOp const& copyOp)
536530
VkImageLayout oldLayout = srcTexture->GetImageLayout();
537531
const auto [srcAccess, srcStage] =
538532
_GetOldAccessAndPipelineStageFlags(oldLayout);
539-
HgiVulkanTexture::TransitionImageBarrier(
533+
srcTexture->LayoutBarrier(
540534
_commandBuffer,
541-
srcTexture,
542535
/*oldLayout*/oldLayout,
543536
/*newLayout*/VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
544537
/*producerAccess*/srcAccess,
@@ -583,9 +576,8 @@ HgiVulkanBlitCmds::CopyTextureToBuffer(HgiTextureToBufferOp const& copyOp)
583576
// Transition image layout back to original layout.
584577
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
585578
srcTexture->GetDescriptor().usage);
586-
HgiVulkanTexture::TransitionImageBarrier(
579+
srcTexture->LayoutBarrier(
587580
_commandBuffer,
588-
srcTexture,
589581
/*oldLayout*/VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
590582
/*newLayout*/oldLayout,
591583
/*producerAccess*/VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -625,9 +617,8 @@ HgiVulkanBlitCmds::CopyBufferToTexture(HgiBufferToTextureOp const& copyOp)
625617
VkImageLayout oldLayout = dstTexture->GetImageLayout();
626618
const auto [srcAccess, srcStage] =
627619
_GetOldAccessAndPipelineStageFlags(oldLayout);
628-
HgiVulkanTexture::TransitionImageBarrier(
620+
dstTexture->LayoutBarrier(
629621
_commandBuffer,
630-
dstTexture,
631622
/*oldLayout*/oldLayout,
632623
/*newLayout*/VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
633624
/*producerAccess*/srcAccess,
@@ -671,9 +662,8 @@ HgiVulkanBlitCmds::CopyBufferToTexture(HgiBufferToTextureOp const& copyOp)
671662
// Transition image layout back to original layout.
672663
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
673664
dstTexture->GetDescriptor().usage);
674-
HgiVulkanTexture::TransitionImageBarrier(
665+
dstTexture->LayoutBarrier(
675666
_commandBuffer,
676-
dstTexture,
677667
/*oldLayout*/VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
678668
/*newLayout*/oldLayout,
679669
/*producerAccess*/VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -717,9 +707,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
717707
const VkImageLayout oldLayout = vkTex->GetImageLayout();
718708
const auto [srcAccess, srcStage] =
719709
_GetOldAccessAndPipelineStageFlags(oldLayout);
720-
HgiVulkanTexture::TransitionImageBarrier(
710+
vkTex->LayoutBarrier(
721711
_commandBuffer,
722-
vkTex,
723712
oldLayout,
724713
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
725714
srcAccess,
@@ -749,9 +738,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
749738
imageBlit.dstOffsets[1].z = 1;
750739

751740
// Transition current mip level to image blit destination
752-
HgiVulkanTexture::TransitionImageBarrier(
741+
vkTex->LayoutBarrier(
753742
_commandBuffer,
754-
vkTex,
755743
oldLayout,
756744
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
757745
srcAccess,
@@ -772,9 +760,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
772760
VK_FILTER_LINEAR);
773761

774762
// Prepare current mip level as image blit source for next level
775-
HgiVulkanTexture::TransitionImageBarrier(
763+
vkTex->LayoutBarrier(
776764
_commandBuffer,
777-
vkTex,
778765
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
779766
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
780767
VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -787,9 +774,8 @@ HgiVulkanBlitCmds::GenerateMipMaps(HgiTextureHandle const& texture)
787774
// Return all mips from TRANSFER_SRC to their original layout
788775
const VkAccessFlags access = HgiVulkanTexture::GetDefaultAccessFlags(
789776
vkTex->GetDescriptor().usage);
790-
HgiVulkanTexture::TransitionImageBarrier(
777+
vkTex->LayoutBarrier(
791778
_commandBuffer,
792-
vkTex,
793779
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
794780
oldLayout,
795781
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)