The test uses the format VK_FORMAT_D16_UNORM for the shadow map, and it sets unconditionally VK_FILTER_LINEAR when using it. But by spec, it is not mandatory that format to support filtering. Explained here: https://www.khronos.org/registry/vulkan/specs/1.2/html/chap32.html table 51, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT. This commit checks if that flag is present with that format to decide between LINEAR (the default value) or NEAREST (if LINEAR is not supported). Adds a auxiliar method on VulkanTools just in case it could be useful for other demos. This is not detected by the Validation Layers, but raise an assertion with one of the development tools we use to implement the Mesa v3dv driver (rpi4 vulkan driver).
129 lines
4.1 KiB
C++
129 lines
4.1 KiB
C++
/*
|
|
* Assorted Vulkan helper functions
|
|
*
|
|
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
|
*
|
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "vulkan/vulkan.h"
|
|
#include "VulkanInitializers.hpp"
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <cstring>
|
|
#include <fstream>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <fstream>
|
|
#if defined(_WIN32)
|
|
#include <windows.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#elif defined(__ANDROID__)
|
|
#include "VulkanAndroid.h"
|
|
#include <android/asset_manager.h>
|
|
#endif
|
|
|
|
// Custom define for better code readability
|
|
#define VK_FLAGS_NONE 0
|
|
// Default fence timeout in nanoseconds
|
|
#define DEFAULT_FENCE_TIMEOUT 100000000000
|
|
|
|
// Macro to check and display Vulkan return results
|
|
#if defined(__ANDROID__)
|
|
#define VK_CHECK_RESULT(f) \
|
|
{ \
|
|
VkResult res = (f); \
|
|
if (res != VK_SUCCESS) \
|
|
{ \
|
|
LOGE("Fatal : VkResult is \" %s \" in %s at line %d", vks::tools::errorString(res).c_str(), __FILE__, __LINE__); \
|
|
assert(res == VK_SUCCESS); \
|
|
} \
|
|
}
|
|
#else
|
|
#define VK_CHECK_RESULT(f) \
|
|
{ \
|
|
VkResult res = (f); \
|
|
if (res != VK_SUCCESS) \
|
|
{ \
|
|
std::cout << "Fatal : VkResult is \"" << vks::tools::errorString(res) << "\" in " << __FILE__ << " at line " << __LINE__ << std::endl; \
|
|
assert(res == VK_SUCCESS); \
|
|
} \
|
|
}
|
|
#endif
|
|
|
|
const std::string getAssetPath();
|
|
|
|
namespace vks
|
|
{
|
|
namespace tools
|
|
{
|
|
/** @brief Disable message boxes on fatal errors */
|
|
extern bool errorModeSilent;
|
|
|
|
/** @brief Returns an error code as a string */
|
|
std::string errorString(VkResult errorCode);
|
|
|
|
/** @brief Returns the device type as a string */
|
|
std::string physicalDeviceTypeString(VkPhysicalDeviceType type);
|
|
|
|
// Selected a suitable supported depth format starting with 32 bit down to 16 bit
|
|
// Returns false if none of the depth formats in the list is supported by the device
|
|
VkBool32 getSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat);
|
|
|
|
// Returns if a given format support LINEAR filtering
|
|
VkBool32 formatIsFilterable(VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling tiling);
|
|
|
|
// Put an image memory barrier for setting an image layout on the sub resource into the given command buffer
|
|
void setImageLayout(
|
|
VkCommandBuffer cmdbuffer,
|
|
VkImage image,
|
|
VkImageLayout oldImageLayout,
|
|
VkImageLayout newImageLayout,
|
|
VkImageSubresourceRange subresourceRange,
|
|
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
|
// Uses a fixed sub resource layout with first mip level and layer
|
|
void setImageLayout(
|
|
VkCommandBuffer cmdbuffer,
|
|
VkImage image,
|
|
VkImageAspectFlags aspectMask,
|
|
VkImageLayout oldImageLayout,
|
|
VkImageLayout newImageLayout,
|
|
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
|
|
|
/** @brief Inser an image memory barrier into the command buffer */
|
|
void insertImageMemoryBarrier(
|
|
VkCommandBuffer cmdbuffer,
|
|
VkImage image,
|
|
VkAccessFlags srcAccessMask,
|
|
VkAccessFlags dstAccessMask,
|
|
VkImageLayout oldImageLayout,
|
|
VkImageLayout newImageLayout,
|
|
VkPipelineStageFlags srcStageMask,
|
|
VkPipelineStageFlags dstStageMask,
|
|
VkImageSubresourceRange subresourceRange);
|
|
|
|
// Display error message and exit on fatal error
|
|
void exitFatal(std::string message, int32_t exitCode);
|
|
void exitFatal(std::string message, VkResult resultCode);
|
|
|
|
// Load a SPIR-V shader (binary)
|
|
#if defined(__ANDROID__)
|
|
VkShaderModule loadShader(AAssetManager* assetManager, const char *fileName, VkDevice device);
|
|
#else
|
|
VkShaderModule loadShader(const char *fileName, VkDevice device);
|
|
#endif
|
|
|
|
/** @brief Checks if a file exists */
|
|
bool fileExists(const std::string &filename);
|
|
}
|
|
}
|