Add additional logic for skip VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

Added checks for:
```
Memory types must not have both VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set.
```
And
```
A memory type with this flag set is only allowed to be bound to a VkImage
whose usage flags include VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT.
```

https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkMemoryPropertyFlagBits.html
This commit is contained in:
Denis Pauk 2022-07-24 00:10:31 +03:00
parent 41057458e4
commit e5f7bf7e82
4 changed files with 41 additions and 15 deletions

View file

@ -49,7 +49,8 @@ typedef struct ImageResource_s {
VkResult buffer_create(BufferResource_t *buf, VkResult buffer_create(BufferResource_t *buf,
VkBufferCreateInfo buf_create_info, VkBufferCreateInfo buf_create_info,
VkMemoryPropertyFlags mem_properties, VkMemoryPropertyFlags mem_properties,
VkMemoryPropertyFlags mem_preferences); VkMemoryPropertyFlags mem_preferences,
VkMemoryPropertyFlags mem_skip);
VkResult buffer_destroy(BufferResource_t *buf); VkResult buffer_destroy(BufferResource_t *buf);
void buffer_unmap(BufferResource_t *buf); void buffer_unmap(BufferResource_t *buf);
@ -60,7 +61,8 @@ VkResult buffer_invalidate(BufferResource_t *buf);
VkResult image_create(ImageResource_t *img, VkResult image_create(ImageResource_t *img,
VkImageCreateInfo img_create_info, VkImageCreateInfo img_create_info,
VkMemoryPropertyFlags mem_properties, VkMemoryPropertyFlags mem_properties,
VkMemoryPropertyFlags mem_preferences); VkMemoryPropertyFlags mem_preferences,
VkMemoryPropertyFlags mem_skip);
VkResult image_destroy(ImageResource_t *img); VkResult image_destroy(ImageResource_t *img);
void vulkan_memory_init(void); void vulkan_memory_init(void);

View file

@ -99,7 +99,8 @@ QVk_CreateBuffer(VkDeviceSize size, qvkbuffer_t *dstBuffer,
dstBuffer->currentOffset = 0; dstBuffer->currentOffset = 0;
return buffer_create(&dstBuffer->resource, bcInfo, return buffer_create(&dstBuffer->resource, bcInfo,
options.reqMemFlags, options.prefMemFlags); options.reqMemFlags, options.prefMemFlags,
/*skip memory*/ 0);
} }
void void
@ -136,7 +137,7 @@ QVk_CreateStagingBuffer(VkDeviceSize size, qvkstagingbuffer_t *dstBuffer,
dstBuffer->currentOffset = 0; dstBuffer->currentOffset = 0;
return buffer_create(&dstBuffer->resource, bcInfo, reqMemFlags, return buffer_create(&dstBuffer->resource, bcInfo, reqMemFlags,
prefMemFlags); prefMemFlags, /*skip memory*/ 0);
} }
VkResult VkResult

View file

@ -316,6 +316,7 @@ VkResult QVk_CreateImageView(const VkImage *image, VkImageAspectFlags aspectFlag
VkResult QVk_CreateImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, qvktexture_t *texture) VkResult QVk_CreateImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, qvktexture_t *texture)
{ {
VkMemoryPropertyFlags mem_skip = 0;
VkImageCreateInfo imageInfo = { VkImageCreateInfo imageInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D, .imageType = VK_IMAGE_TYPE_2D,
@ -341,11 +342,17 @@ VkResult QVk_CreateImage(uint32_t width, uint32_t height, VkFormat format, VkIma
imageInfo.pQueueFamilyIndices = queueFamilies; imageInfo.pQueueFamilyIndices = queueFamilies;
} }
if (!(usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT))
{
mem_skip |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
}
texture->sharingMode = imageInfo.sharingMode; texture->sharingMode = imageInfo.sharingMode;
return image_create( return image_create(
&texture->resource, imageInfo, &texture->resource, imageInfo,
/*mem_properties*/ 0, /*mem_properties*/ 0,
/*mem_preferences*/ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); /*mem_preferences*/ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
/*mem_skip*/ mem_skip);
} }
void QVk_CreateDepthBuffer(VkSampleCountFlagBits sampleCount, qvktexture_t *depthBuffer) void QVk_CreateDepthBuffer(VkSampleCountFlagBits sampleCount, qvktexture_t *depthBuffer)
@ -517,7 +524,10 @@ void QVk_ReadPixels(uint8_t *dstBuffer, const VkOffset2D *offset, const VkExtent
.pQueueFamilyIndices = NULL, .pQueueFamilyIndices = NULL,
}; };
VK_VERIFY(buffer_create(&buff, bcInfo, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_CACHED_BIT)); VK_VERIFY(buffer_create(&buff, bcInfo,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
0));
cmdBuffer = QVk_CreateCommandBuffer(&vk_commandPool[vk_activeBufferIdx], VK_COMMAND_BUFFER_LEVEL_PRIMARY); cmdBuffer = QVk_CreateCommandBuffer(&vk_commandPool[vk_activeBufferIdx], VK_COMMAND_BUFFER_LEVEL_PRIMARY);
VK_VERIFY(QVk_BeginCommand(&cmdBuffer)); VK_VERIFY(QVk_BeginCommand(&cmdBuffer));

View file

@ -49,17 +49,27 @@ static inline uint32_t count_bits_set(uint32_t v)
static uint32_t static uint32_t
get_memory_type(uint32_t mem_req_type_bits, get_memory_type(uint32_t mem_req_type_bits,
VkMemoryPropertyFlags mem_prop, VkMemoryPropertyFlags mem_prop,
VkMemoryPropertyFlags mem_pref) VkMemoryPropertyFlags mem_pref,
VkMemoryPropertyFlags mem_skip)
{ {
uint32_t mem_type_index = VK_MAX_MEMORY_TYPES; uint32_t mem_type_index = VK_MAX_MEMORY_TYPES;
int max_cost = 0; int max_cost = 0;
// update prefered with requiredVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT // update prefered with required
mem_pref |= mem_prop; mem_pref |= mem_prop;
// skip for host visible memory
if (mem_pref & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
{
mem_skip |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
}
for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) { for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
if(mem_req_type_bits & (1 << i)) { if(mem_req_type_bits & (1 << i)) {
// This memory type contains mem_prop. // This memory type contains mem_prop and no mem_skip
if((vk_device.mem_properties.memoryTypes[i].propertyFlags & mem_prop) == mem_prop) if(
(vk_device.mem_properties.memoryTypes[i].propertyFlags & mem_prop) == mem_prop &&
!(vk_device.mem_properties.memoryTypes[i].propertyFlags & mem_skip)
)
{ {
#if defined(__APPLE__) #if defined(__APPLE__)
// code has some flags issues with MoltenVK // code has some flags issues with MoltenVK
@ -432,6 +442,7 @@ static VkResult
memory_create_by_property(VkMemoryRequirements* mem_reqs, memory_create_by_property(VkMemoryRequirements* mem_reqs,
VkMemoryPropertyFlags mem_properties, VkMemoryPropertyFlags mem_properties,
VkMemoryPropertyFlags mem_preferences, VkMemoryPropertyFlags mem_preferences,
VkMemoryPropertyFlags mem_skip,
VkDeviceMemory *memory, VkDeviceMemory *memory,
VkDeviceSize *offset) VkDeviceSize *offset)
{ {
@ -439,7 +450,7 @@ memory_create_by_property(VkMemoryRequirements* mem_reqs,
VkMemoryPropertyFlags host_visible; VkMemoryPropertyFlags host_visible;
memory_index = get_memory_type(mem_reqs->memoryTypeBits, memory_index = get_memory_type(mem_reqs->memoryTypeBits,
mem_properties, mem_preferences); mem_properties, mem_preferences, mem_skip);
if (memory_index == VK_MAX_MEMORY_TYPES) if (memory_index == VK_MAX_MEMORY_TYPES)
{ {
@ -460,7 +471,8 @@ VkResult
buffer_create(BufferResource_t *buf, buffer_create(BufferResource_t *buf,
VkBufferCreateInfo buf_create_info, VkBufferCreateInfo buf_create_info,
VkMemoryPropertyFlags mem_properties, VkMemoryPropertyFlags mem_properties,
VkMemoryPropertyFlags mem_preferences) VkMemoryPropertyFlags mem_preferences,
VkMemoryPropertyFlags mem_skip)
{ {
assert(buf_create_info.size > 0); assert(buf_create_info.size > 0);
assert(buf); assert(buf);
@ -481,7 +493,7 @@ buffer_create(BufferResource_t *buf,
vkGetBufferMemoryRequirements(vk_device.logical, buf->buffer, &mem_reqs); vkGetBufferMemoryRequirements(vk_device.logical, buf->buffer, &mem_reqs);
result = memory_create_by_property(&mem_reqs, mem_properties, mem_preferences, result = memory_create_by_property(&mem_reqs, mem_properties, mem_preferences,
&buf->memory, &buf->offset); mem_skip, &buf->memory, &buf->offset);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
R_Printf(PRINT_ALL, "%s:%d: VkResult verification: %s\n", R_Printf(PRINT_ALL, "%s:%d: VkResult verification: %s\n",
__func__, __LINE__, QVk_GetError(result)); __func__, __LINE__, QVk_GetError(result));
@ -514,7 +526,8 @@ VkResult
image_create(ImageResource_t *img, image_create(ImageResource_t *img,
VkImageCreateInfo img_create_info, VkImageCreateInfo img_create_info,
VkMemoryPropertyFlags mem_properties, VkMemoryPropertyFlags mem_properties,
VkMemoryPropertyFlags mem_preferences) VkMemoryPropertyFlags mem_preferences,
VkMemoryPropertyFlags mem_skip)
{ {
assert(img); assert(img);
VkResult result = VK_SUCCESS; VkResult result = VK_SUCCESS;
@ -532,7 +545,7 @@ image_create(ImageResource_t *img,
img->size = mem_reqs.size; img->size = mem_reqs.size;
result = memory_create_by_property(&mem_reqs, mem_properties, mem_preferences, result = memory_create_by_property(&mem_reqs, mem_properties, mem_preferences,
&img->memory, &img->offset); mem_skip, &img->memory, &img->offset);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
R_Printf(PRINT_ALL, "%s:%d: VkResult verification: %s\n", R_Printf(PRINT_ALL, "%s:%d: VkResult verification: %s\n",
__func__, __LINE__, QVk_GetError(result)); __func__, __LINE__, QVk_GetError(result));