2020-12-17 00:27:14 +00:00
|
|
|
/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities
|
|
|
|
*
|
|
|
|
* Copyright (c) 2020 Evan Hemsley
|
|
|
|
*
|
|
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
|
|
* In no event will the authors be held liable for any damages arising from
|
|
|
|
* the use of this software.
|
|
|
|
*
|
|
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
|
|
* including commercial applications, and to alter it and redistribute it
|
|
|
|
* freely, subject to the following restrictions:
|
|
|
|
*
|
|
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
|
|
* claim that you wrote the original software. If you use this software in a
|
|
|
|
* product, an acknowledgment in the product documentation would be
|
|
|
|
* appreciated but is not required.
|
|
|
|
*
|
|
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
* misrepresented as being the original software.
|
|
|
|
*
|
|
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*
|
|
|
|
* Evan "cosmonaut" Hemsley <evan@moonside.games>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if REFRESH_DRIVER_VULKAN
|
|
|
|
|
|
|
|
#define VK_NO_PROTOTYPES
|
|
|
|
#include "vulkan/vulkan.h"
|
|
|
|
|
|
|
|
#include "Refresh_Driver.h"
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
#include <SDL_syswm.h>
|
|
|
|
#include <SDL_vulkan.h>
|
|
|
|
|
2020-12-17 02:38:22 +00:00
|
|
|
/* Global Vulkan Loader Entry Points */
|
|
|
|
|
|
|
|
static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
|
|
|
|
|
|
|
|
#define VULKAN_GLOBAL_FUNCTION(name) \
|
|
|
|
static PFN_##name name = NULL;
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
|
|
|
|
|
|
|
/* vkInstance/vkDevice function typedefs */
|
|
|
|
|
|
|
|
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
|
|
|
typedef ret (VKAPI_CALL *vkfntype_##func) params;
|
|
|
|
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
|
|
|
|
typedef ret (VKAPI_CALL *vkfntype_##func) params;
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
|
|
|
|
|
|
|
/* Required extensions */
|
|
|
|
static const char* deviceExtensionNames[] =
|
|
|
|
{
|
|
|
|
/* Globally supported */
|
|
|
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
|
|
|
/* Core since 1.1 */
|
|
|
|
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
|
|
|
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
|
|
|
|
VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
|
|
|
|
/* Core since 1.2 */
|
|
|
|
VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
|
|
|
|
/* EXT, probably not going to be Core */
|
|
|
|
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
|
|
|
|
};
|
|
|
|
static uint32_t deviceExtensionCount = SDL_arraysize(deviceExtensionNames);
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
/* Defines */
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */
|
|
|
|
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
|
|
|
|
#define TEXTURE_STAGING_SIZE 8000000 /* 8MB */
|
|
|
|
#define UBO_BUFFER_SIZE 8000000 /* 8MB */
|
|
|
|
#define UBO_ACTUAL_SIZE (UBO_BUFFER_SIZE * 2)
|
|
|
|
#define SAMPLER_POOL_SIZE 100
|
2020-12-23 21:11:09 +00:00
|
|
|
#define UBO_POOL_SIZE 1000
|
2020-12-19 04:08:07 +00:00
|
|
|
#define SUB_BUFFER_COUNT 2
|
2020-12-18 22:35:33 +00:00
|
|
|
|
|
|
|
#define IDENTITY_SWIZZLE \
|
|
|
|
{ \
|
|
|
|
VK_COMPONENT_SWIZZLE_IDENTITY, \
|
|
|
|
VK_COMPONENT_SWIZZLE_IDENTITY, \
|
|
|
|
VK_COMPONENT_SWIZZLE_IDENTITY, \
|
|
|
|
VK_COMPONENT_SWIZZLE_IDENTITY \
|
|
|
|
}
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
#define NULL_RENDER_PASS (REFRESH_RenderPass*) 0
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
/* Enums */
|
|
|
|
|
|
|
|
typedef enum VulkanResourceAccessType
|
|
|
|
{
|
|
|
|
/* Reads */
|
|
|
|
RESOURCE_ACCESS_NONE, /* For initialization */
|
|
|
|
RESOURCE_ACCESS_INDEX_BUFFER,
|
|
|
|
RESOURCE_ACCESS_VERTEX_BUFFER,
|
|
|
|
RESOURCE_ACCESS_VERTEX_SHADER_READ_UNIFORM_BUFFER,
|
|
|
|
RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_UNIFORM_BUFFER,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_COLOR_ATTACHMENT,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_DEPTH_STENCIL_ATTACHMENT,
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_READ,
|
|
|
|
RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_READ,
|
|
|
|
RESOURCE_ACCESS_HOST_READ,
|
|
|
|
RESOURCE_ACCESS_PRESENT,
|
|
|
|
RESOURCE_ACCESS_END_OF_READ,
|
|
|
|
|
|
|
|
/* Writes */
|
|
|
|
RESOURCE_ACCESS_VERTEX_SHADER_WRITE,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_WRITE,
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE,
|
|
|
|
RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
RESOURCE_ACCESS_HOST_WRITE,
|
|
|
|
|
|
|
|
/* Read-Writes */
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE,
|
|
|
|
RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_WRITE,
|
|
|
|
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
|
|
|
|
RESOURCE_ACCESS_GENERAL,
|
|
|
|
|
|
|
|
/* Count */
|
|
|
|
RESOURCE_ACCESS_TYPES_COUNT
|
|
|
|
} VulkanResourceAccessType;
|
|
|
|
|
2020-12-17 03:50:31 +00:00
|
|
|
typedef enum CreateSwapchainResult
|
|
|
|
{
|
|
|
|
CREATE_SWAPCHAIN_FAIL,
|
|
|
|
CREATE_SWAPCHAIN_SUCCESS,
|
|
|
|
CREATE_SWAPCHAIN_SURFACE_ZERO,
|
|
|
|
} CreateSwapchainResult;
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
/* Conversions */
|
|
|
|
|
|
|
|
static VkFormat RefreshToVK_SurfaceFormat[] =
|
|
|
|
{
|
|
|
|
VK_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */
|
|
|
|
VK_FORMAT_R5G6B5_UNORM_PACK16, /* R5G6B5 */
|
|
|
|
VK_FORMAT_A1R5G5B5_UNORM_PACK16, /* A1R5G5B5 */
|
|
|
|
VK_FORMAT_B4G4R4A4_UNORM_PACK16, /* B4G4R4A4 */
|
|
|
|
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, /* BC1 */
|
|
|
|
VK_FORMAT_BC2_UNORM_BLOCK, /* BC3 */
|
|
|
|
VK_FORMAT_BC3_UNORM_BLOCK, /* BC5 */
|
|
|
|
VK_FORMAT_R8G8_SNORM, /* R8G8_SNORM */
|
|
|
|
VK_FORMAT_R8G8B8A8_SNORM, /* R8G8B8A8_SNORM */
|
|
|
|
VK_FORMAT_A2R10G10B10_UNORM_PACK32, /* A2R10G10B10 */
|
|
|
|
VK_FORMAT_R16G16_UNORM, /* R16G16 */
|
|
|
|
VK_FORMAT_R16G16B16A16_UNORM, /* R16G16B16A16 */
|
|
|
|
VK_FORMAT_R8_UNORM, /* R8 */
|
|
|
|
VK_FORMAT_R32_SFLOAT, /* R32_SFLOAT */
|
|
|
|
VK_FORMAT_R32G32_SFLOAT, /* R32G32_SFLOAT */
|
|
|
|
VK_FORMAT_R32G32B32A32_SFLOAT, /* R32G32B32A32_SFLOAT */
|
|
|
|
VK_FORMAT_R16_SFLOAT, /* R16_SFLOAT */
|
|
|
|
VK_FORMAT_R16G16_SFLOAT, /* R16G16_SFLOAT */
|
|
|
|
VK_FORMAT_R16G16B16A16_SFLOAT /* R16G16B16A16_SFLOAT */
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkFormat RefreshToVK_DepthFormat[] =
|
|
|
|
{
|
|
|
|
VK_FORMAT_D16_UNORM,
|
|
|
|
VK_FORMAT_D32_SFLOAT,
|
|
|
|
VK_FORMAT_D16_UNORM_S8_UINT,
|
|
|
|
VK_FORMAT_D24_UNORM_S8_UINT,
|
|
|
|
VK_FORMAT_D32_SFLOAT_S8_UINT
|
|
|
|
};
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
static VkFormat RefreshToVK_VertexFormat[] =
|
|
|
|
{
|
|
|
|
VK_FORMAT_R32_SFLOAT, /* SINGLE */
|
|
|
|
VK_FORMAT_R32G32_SFLOAT, /* VECTOR2 */
|
|
|
|
VK_FORMAT_R32G32B32_SFLOAT, /* VECTOR3 */
|
|
|
|
VK_FORMAT_R32G32B32A32_SFLOAT, /* VECTOR4 */
|
|
|
|
VK_FORMAT_R8G8B8A8_UNORM, /* COLOR */
|
|
|
|
VK_FORMAT_R8G8B8A8_USCALED, /* BYTE4 */
|
|
|
|
VK_FORMAT_R16G16_SSCALED, /* SHORT2 */
|
|
|
|
VK_FORMAT_R16G16B16A16_SSCALED, /* SHORT4 */
|
|
|
|
VK_FORMAT_R16G16_SNORM, /* NORMALIZEDSHORT2 */
|
|
|
|
VK_FORMAT_R16G16B16A16_SNORM, /* NORMALIZEDSHORT4 */
|
|
|
|
VK_FORMAT_R16G16_SFLOAT, /* HALFVECTOR2 */
|
|
|
|
VK_FORMAT_R16G16B16A16_SFLOAT /* HALFVECTOR4 */
|
|
|
|
};
|
|
|
|
|
2020-12-20 07:31:55 +00:00
|
|
|
static VkIndexType RefreshToVK_IndexType[] =
|
|
|
|
{
|
|
|
|
VK_INDEX_TYPE_UINT16,
|
|
|
|
VK_INDEX_TYPE_UINT32
|
|
|
|
};
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
static VkPrimitiveTopology RefreshToVK_PrimitiveType[] =
|
|
|
|
{
|
|
|
|
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
|
|
|
|
VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
|
|
|
|
VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
|
|
|
|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
|
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkPolygonMode RefreshToVK_PolygonMode[] =
|
|
|
|
{
|
|
|
|
VK_POLYGON_MODE_FILL,
|
|
|
|
VK_POLYGON_MODE_LINE,
|
|
|
|
VK_POLYGON_MODE_POINT
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkCullModeFlags RefreshToVK_CullMode[] =
|
|
|
|
{
|
|
|
|
VK_CULL_MODE_NONE,
|
|
|
|
VK_CULL_MODE_FRONT_BIT,
|
|
|
|
VK_CULL_MODE_BACK_BIT,
|
|
|
|
VK_CULL_MODE_FRONT_AND_BACK
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkFrontFace RefreshToVK_FrontFace[] =
|
|
|
|
{
|
|
|
|
VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
|
|
|
VK_FRONT_FACE_CLOCKWISE
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkBlendFactor RefreshToVK_BlendFactor[] =
|
|
|
|
{
|
|
|
|
VK_BLEND_FACTOR_ZERO,
|
|
|
|
VK_BLEND_FACTOR_ONE,
|
|
|
|
VK_BLEND_FACTOR_SRC_COLOR,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
|
|
|
|
VK_BLEND_FACTOR_DST_COLOR,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
|
|
|
|
VK_BLEND_FACTOR_SRC_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_DST_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_CONSTANT_COLOR,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
|
|
|
|
VK_BLEND_FACTOR_CONSTANT_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
|
|
|
|
VK_BLEND_FACTOR_SRC1_COLOR,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
|
|
|
|
VK_BLEND_FACTOR_SRC1_ALPHA,
|
|
|
|
VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkBlendOp RefreshToVK_BlendOp[] =
|
|
|
|
{
|
|
|
|
VK_BLEND_OP_ADD,
|
|
|
|
VK_BLEND_OP_SUBTRACT,
|
|
|
|
VK_BLEND_OP_REVERSE_SUBTRACT,
|
|
|
|
VK_BLEND_OP_MIN,
|
|
|
|
VK_BLEND_OP_MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkLogicOp RefreshToVK_LogicOp[] =
|
|
|
|
{
|
|
|
|
VK_LOGIC_OP_CLEAR,
|
|
|
|
VK_LOGIC_OP_AND,
|
|
|
|
VK_LOGIC_OP_AND_REVERSE,
|
|
|
|
VK_LOGIC_OP_COPY,
|
|
|
|
VK_LOGIC_OP_AND_INVERTED,
|
|
|
|
VK_LOGIC_OP_NO_OP,
|
|
|
|
VK_LOGIC_OP_XOR,
|
|
|
|
VK_LOGIC_OP_OR,
|
|
|
|
VK_LOGIC_OP_NOR,
|
|
|
|
VK_LOGIC_OP_EQUIVALENT,
|
|
|
|
VK_LOGIC_OP_INVERT,
|
|
|
|
VK_LOGIC_OP_OR_REVERSE,
|
|
|
|
VK_LOGIC_OP_COPY_INVERTED,
|
|
|
|
VK_LOGIC_OP_OR_INVERTED,
|
|
|
|
VK_LOGIC_OP_NAND,
|
|
|
|
VK_LOGIC_OP_SET
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkCompareOp RefreshToVK_CompareOp[] =
|
|
|
|
{
|
|
|
|
VK_COMPARE_OP_NEVER,
|
|
|
|
VK_COMPARE_OP_LESS,
|
|
|
|
VK_COMPARE_OP_EQUAL,
|
|
|
|
VK_COMPARE_OP_LESS_OR_EQUAL,
|
|
|
|
VK_COMPARE_OP_GREATER,
|
|
|
|
VK_COMPARE_OP_NOT_EQUAL,
|
|
|
|
VK_COMPARE_OP_GREATER_OR_EQUAL,
|
|
|
|
VK_COMPARE_OP_ALWAYS
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkStencilOp RefreshToVK_StencilOp[] =
|
|
|
|
{
|
|
|
|
VK_STENCIL_OP_KEEP,
|
|
|
|
VK_STENCIL_OP_ZERO,
|
|
|
|
VK_STENCIL_OP_REPLACE,
|
|
|
|
VK_STENCIL_OP_INCREMENT_AND_CLAMP,
|
|
|
|
VK_STENCIL_OP_DECREMENT_AND_CLAMP,
|
|
|
|
VK_STENCIL_OP_INVERT,
|
|
|
|
VK_STENCIL_OP_INCREMENT_AND_WRAP,
|
|
|
|
VK_STENCIL_OP_DECREMENT_AND_WRAP
|
|
|
|
};
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
static VkAttachmentLoadOp RefreshToVK_LoadOp[] =
|
|
|
|
{
|
|
|
|
VK_ATTACHMENT_LOAD_OP_LOAD,
|
|
|
|
VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkAttachmentStoreOp RefreshToVK_StoreOp[] =
|
|
|
|
{
|
|
|
|
VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
VK_ATTACHMENT_STORE_OP_DONT_CARE
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkSampleCountFlagBits RefreshToVK_SampleCount[] =
|
|
|
|
{
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
VK_SAMPLE_COUNT_2_BIT,
|
|
|
|
VK_SAMPLE_COUNT_4_BIT,
|
|
|
|
VK_SAMPLE_COUNT_8_BIT,
|
|
|
|
VK_SAMPLE_COUNT_16_BIT,
|
|
|
|
VK_SAMPLE_COUNT_32_BIT,
|
|
|
|
VK_SAMPLE_COUNT_64_BIT
|
|
|
|
};
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
static VkVertexInputRate RefreshToVK_VertexInputRate[] =
|
|
|
|
{
|
|
|
|
VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
VK_VERTEX_INPUT_RATE_INSTANCE
|
|
|
|
};
|
|
|
|
|
2020-12-18 01:48:26 +00:00
|
|
|
static VkFilter RefreshToVK_SamplerFilter[] =
|
|
|
|
{
|
|
|
|
VK_FILTER_NEAREST,
|
|
|
|
VK_FILTER_LINEAR
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkSamplerMipmapMode RefreshToVK_SamplerMipmapMode[] =
|
|
|
|
{
|
|
|
|
VK_SAMPLER_MIPMAP_MODE_NEAREST,
|
|
|
|
VK_SAMPLER_MIPMAP_MODE_LINEAR
|
|
|
|
};
|
|
|
|
|
|
|
|
static VkSamplerAddressMode RefreshToVK_SamplerAddressMode[] =
|
|
|
|
{
|
|
|
|
VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
|
|
|
VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
|
|
|
|
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
|
|
|
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER
|
|
|
|
};
|
|
|
|
|
2020-12-18 20:58:03 +00:00
|
|
|
static VkBorderColor RefreshToVK_BorderColor[] =
|
|
|
|
{
|
|
|
|
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
|
|
|
|
VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,
|
|
|
|
VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
|
|
|
|
VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
|
|
|
VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
|
|
|
|
VK_BORDER_COLOR_INT_OPAQUE_WHITE
|
|
|
|
};
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
/* Structures */
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* Memory Allocation */
|
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
|
|
|
|
|
|
|
|
typedef struct VulkanMemoryFreeRegion
|
|
|
|
{
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize size;
|
|
|
|
uint32_t allocationIndex;
|
|
|
|
uint32_t sortedIndex;
|
|
|
|
} VulkanMemoryFreeRegion;
|
|
|
|
|
|
|
|
typedef struct VulkanMemorySubAllocator
|
|
|
|
{
|
|
|
|
VkDeviceSize nextAllocationSize;
|
|
|
|
VulkanMemoryAllocation **allocations;
|
|
|
|
uint32_t allocationCount;
|
|
|
|
VulkanMemoryFreeRegion **sortedFreeRegions;
|
|
|
|
uint32_t sortedFreeRegionCount;
|
|
|
|
uint32_t sortedFreeRegionCapacity;
|
|
|
|
} VulkanMemorySubAllocator;
|
|
|
|
|
|
|
|
struct VulkanMemoryAllocation
|
|
|
|
{
|
|
|
|
VulkanMemorySubAllocator *allocator;
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
VkDeviceSize size;
|
|
|
|
VulkanMemoryFreeRegion **freeRegions;
|
|
|
|
uint32_t freeRegionCount;
|
|
|
|
uint32_t freeRegionCapacity;
|
|
|
|
uint8_t dedicated;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct VulkanMemoryAllocator
|
|
|
|
{
|
|
|
|
VulkanMemorySubAllocator subAllocators[VK_MAX_MEMORY_TYPES];
|
|
|
|
} VulkanMemoryAllocator;
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* Memory Barriers */
|
|
|
|
|
|
|
|
typedef struct VulkanResourceAccessInfo
|
|
|
|
{
|
|
|
|
VkPipelineStageFlags stageMask;
|
|
|
|
VkAccessFlags accessMask;
|
|
|
|
VkImageLayout imageLayout;
|
|
|
|
} VulkanResourceAccessInfo;
|
|
|
|
|
|
|
|
static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] =
|
|
|
|
{
|
|
|
|
/* RESOURCE_ACCESS_NONE */
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_INDEX_BUFFER */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
|
|
|
|
VK_ACCESS_INDEX_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_VERTEX_BUFFER */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
|
|
|
|
VK_ACCESS_INDEX_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_VERTEX_SHADER_READ_UNIFORM_BUFFER */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
|
|
|
VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
|
|
|
VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_FRAGMENT_SHADER_READ_UNIFORM_BUFFER */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_ACCESS_UNIFORM_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_ACCESS_SHADER_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_FRAGMENT_SHADER_READ_COLOR_ATTACHMENT */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_FRAGMENT_SHADER_READ_DEPTH_STENCIL_ATTACHMENT */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_COLOR_ATTACHMENT_READ */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
|
|
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_TRANSFER_READ */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
VK_ACCESS_TRANSFER_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_HOST_READ */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_HOST_BIT,
|
|
|
|
VK_ACCESS_HOST_READ_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_PRESENT */
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_END_OF_READ */
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_VERTEX_SHADER_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
|
|
|
|
VK_ACCESS_SHADER_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_FRAGMENT_SHADER_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
VK_ACCESS_SHADER_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
|
|
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_TRANSFER_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_HOST_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_HOST_BIT,
|
|
|
|
VK_ACCESS_HOST_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
|
|
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_UNDEFINED
|
|
|
|
},
|
|
|
|
|
|
|
|
/* RESOURCE_ACCESS_GENERAL */
|
|
|
|
{
|
|
|
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
|
|
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
typedef struct VulkanBuffer VulkanBuffer;
|
|
|
|
|
|
|
|
typedef struct VulkanSubBuffer
|
2020-12-19 01:03:26 +00:00
|
|
|
{
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VkBuffer buffer;
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize size;
|
|
|
|
VulkanResourceAccessType resourceAccessType;
|
|
|
|
int8_t bound;
|
2020-12-19 04:08:07 +00:00
|
|
|
} VulkanSubBuffer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Our VulkanBuffer is actually a series of sub-buffers
|
|
|
|
* so we can properly support updates while a frame is in flight
|
|
|
|
* without needing a sync point
|
|
|
|
*/
|
|
|
|
struct VulkanBuffer /* cast from FNA3D_Buffer */
|
|
|
|
{
|
|
|
|
VkDeviceSize size;
|
|
|
|
VulkanSubBuffer **subBuffers;
|
2020-12-21 20:37:54 +00:00
|
|
|
uint32_t subBufferCount;
|
2020-12-23 06:05:01 +00:00
|
|
|
uint32_t currentSubBufferIndex;
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanResourceAccessType resourceAccessType;
|
|
|
|
VkBufferUsageFlags usage;
|
|
|
|
uint8_t bound;
|
|
|
|
uint8_t boundSubmitted;
|
|
|
|
};
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* Renderer Structure */
|
|
|
|
|
2020-12-17 02:38:22 +00:00
|
|
|
typedef struct QueueFamilyIndices
|
|
|
|
{
|
|
|
|
uint32_t graphicsFamily;
|
|
|
|
uint32_t presentFamily;
|
|
|
|
} QueueFamilyIndices;
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
typedef struct SwapChainSupportDetails
|
|
|
|
{
|
|
|
|
VkSurfaceCapabilitiesKHR capabilities;
|
|
|
|
VkSurfaceFormatKHR *formats;
|
|
|
|
uint32_t formatsLength;
|
|
|
|
VkPresentModeKHR *presentModes;
|
|
|
|
uint32_t presentModesLength;
|
|
|
|
} SwapChainSupportDetails;
|
|
|
|
|
2020-12-23 06:56:26 +00:00
|
|
|
typedef struct VulkanGraphicsPipeline
|
|
|
|
{
|
|
|
|
VkPipeline pipeline;
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
REFRESH_PrimitiveType primitiveType;
|
|
|
|
VkDescriptorPool descriptorPool;
|
|
|
|
VkDescriptorSetLayout vertexSamplerLayout;
|
|
|
|
uint32_t vertexSamplerBindingCount;
|
|
|
|
VkDescriptorSetLayout fragmentSamplerLayout;
|
|
|
|
uint32_t fragmentSamplerBindingCount;
|
|
|
|
VkDescriptorSet vertexSamplerDescriptorSet; /* updated by SetVertexSamplers */
|
|
|
|
VkDescriptorSet fragmentSamplerDescriptorSet; /* updated by SetFragmentSamplers */
|
2020-12-23 21:11:09 +00:00
|
|
|
|
|
|
|
VkDescriptorSet vertexUBODescriptorSet; /* permanently set in Create function */
|
|
|
|
VkDescriptorSet fragmentUBODescriptorSet; /* permanently set in Create function */
|
|
|
|
VkDeviceSize vertexUBOBlockSize; /* permanently set in Create function */
|
|
|
|
VkDeviceSize fragmentUBOBlockSize; /* permantenly set in Create function */
|
2020-12-23 06:56:26 +00:00
|
|
|
} VulkanGraphicsPipeline;
|
|
|
|
|
2020-12-23 07:17:09 +00:00
|
|
|
typedef struct VulkanTexture
|
|
|
|
{
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize memorySize;
|
|
|
|
|
|
|
|
VkImage image;
|
|
|
|
VkImageView view;
|
|
|
|
VkExtent2D dimensions;
|
|
|
|
uint32_t depth;
|
|
|
|
uint32_t layerCount;
|
|
|
|
uint32_t levelCount;
|
|
|
|
VkFormat format;
|
|
|
|
VulkanResourceAccessType resourceAccessType;
|
|
|
|
} VulkanTexture;
|
|
|
|
|
|
|
|
typedef struct VulkanDepthStencilTexture
|
|
|
|
{
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VkDeviceSize offset;
|
|
|
|
VkDeviceSize memorySize;
|
|
|
|
|
|
|
|
VkImage image;
|
|
|
|
VkImageView view;
|
|
|
|
VkExtent2D dimensions;
|
|
|
|
VkFormat format;
|
|
|
|
VulkanResourceAccessType resourceAccessType;
|
|
|
|
} VulkanDepthStencilTexture;
|
|
|
|
|
|
|
|
typedef struct VulkanColorTarget
|
|
|
|
{
|
|
|
|
VulkanTexture *texture;
|
|
|
|
uint32_t layer;
|
|
|
|
VkImageView view;
|
|
|
|
VulkanTexture *multisampleTexture;
|
|
|
|
VkSampleCountFlags multisampleCount;
|
|
|
|
} VulkanColorTarget;
|
|
|
|
|
|
|
|
typedef struct VulkanDepthStencilTarget
|
|
|
|
{
|
|
|
|
VulkanDepthStencilTexture *texture;
|
|
|
|
VkImageView view;
|
|
|
|
} VulkanDepthStencilTarget;
|
|
|
|
|
|
|
|
typedef struct VulkanFramebuffer
|
|
|
|
{
|
|
|
|
VkFramebuffer framebuffer;
|
|
|
|
VulkanColorTarget *colorTargets[MAX_COLOR_TARGET_BINDINGS];
|
|
|
|
uint32_t colorTargetCount;
|
|
|
|
VulkanDepthStencilTarget *depthStencilTarget;
|
|
|
|
} VulkanFramebuffer;
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
typedef struct VulkanRenderer
|
2020-12-17 01:23:49 +00:00
|
|
|
{
|
2020-12-17 02:12:20 +00:00
|
|
|
VkInstance instance;
|
2020-12-17 02:38:22 +00:00
|
|
|
VkPhysicalDevice physicalDevice;
|
|
|
|
VkPhysicalDeviceProperties2 physicalDeviceProperties;
|
|
|
|
VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
|
|
|
|
VkDevice logicalDevice;
|
|
|
|
|
|
|
|
void* deviceWindowHandle;
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
uint8_t supportsDebugUtils;
|
|
|
|
uint8_t debugMode;
|
2020-12-17 03:50:31 +00:00
|
|
|
uint8_t headless;
|
2020-12-17 03:28:02 +00:00
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
VulkanMemoryAllocator *memoryAllocator;
|
|
|
|
|
2020-12-17 03:50:31 +00:00
|
|
|
REFRESH_PresentMode presentMode;
|
2020-12-17 03:28:02 +00:00
|
|
|
VkSurfaceKHR surface;
|
2020-12-17 03:50:31 +00:00
|
|
|
VkSwapchainKHR swapChain;
|
|
|
|
VkFormat swapChainFormat;
|
|
|
|
VkComponentMapping swapChainSwizzle;
|
|
|
|
VkImage *swapChainImages;
|
|
|
|
VkImageView *swapChainImageViews;
|
2020-12-17 03:28:02 +00:00
|
|
|
VulkanResourceAccessType *swapChainResourceAccessTypes;
|
2020-12-17 03:50:31 +00:00
|
|
|
uint32_t swapChainImageCount;
|
|
|
|
VkExtent2D swapChainExtent;
|
2020-12-22 00:18:21 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
uint8_t needNewSwapChain;
|
|
|
|
uint8_t shouldPresent;
|
|
|
|
uint8_t swapChainImageAcquired;
|
|
|
|
uint32_t currentSwapChainIndex;
|
2020-12-17 03:28:02 +00:00
|
|
|
|
2020-12-17 02:38:22 +00:00
|
|
|
QueueFamilyIndices queueFamilyIndices;
|
|
|
|
VkQueue graphicsQueue;
|
|
|
|
VkQueue presentQueue;
|
|
|
|
|
2020-12-17 04:04:47 +00:00
|
|
|
VkFence inFlightFence;
|
|
|
|
VkSemaphore imageAvailableSemaphore;
|
|
|
|
VkSemaphore renderFinishedSemaphore;
|
|
|
|
|
2020-12-17 02:38:22 +00:00
|
|
|
VkCommandPool commandPool;
|
|
|
|
VkCommandBuffer *inactiveCommandBuffers;
|
|
|
|
VkCommandBuffer *activeCommandBuffers;
|
|
|
|
VkCommandBuffer *submittedCommandBuffers;
|
|
|
|
uint32_t inactiveCommandBufferCount;
|
|
|
|
uint32_t activeCommandBufferCount;
|
|
|
|
uint32_t submittedCommandBufferCount;
|
|
|
|
uint32_t allocatedCommandBufferCount;
|
|
|
|
uint32_t currentCommandCount;
|
|
|
|
VkCommandBuffer currentCommandBuffer;
|
|
|
|
uint32_t numActiveCommands;
|
|
|
|
|
2020-12-23 06:56:26 +00:00
|
|
|
VulkanGraphicsPipeline *currentGraphicsPipeline;
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
/*
|
|
|
|
* TODO: we can get rid of this reference when we
|
|
|
|
* come up with a clever descriptor set reuse system
|
|
|
|
*/
|
|
|
|
VkDescriptorPool *descriptorPools;
|
|
|
|
uint32_t descriptorPoolCount;
|
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
/* initialize baseline descriptor info */
|
|
|
|
VkDescriptorPool defaultDescriptorPool;
|
|
|
|
VkDescriptorSetLayout emptyVertexSamplerLayout;
|
|
|
|
VkDescriptorSetLayout emptyFragmentSamplerLayout;
|
|
|
|
VkDescriptorSet emptyVertexSamplerDescriptorSet;
|
|
|
|
VkDescriptorSet emptyFragmentSamplerDescriptorSet;
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
VkDescriptorSetLayout vertexParamLayout;
|
|
|
|
VkDescriptorSetLayout fragmentParamLayout;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanBuffer *textureStagingBuffer;
|
2020-12-21 21:02:07 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VulkanBuffer** buffersInUse;
|
|
|
|
uint32_t buffersInUseCount;
|
|
|
|
uint32_t buffersInUseCapacity;
|
|
|
|
|
|
|
|
VulkanBuffer** submittedBuffers;
|
|
|
|
uint32_t submittedBufferCount;
|
|
|
|
uint32_t submittedBufferCapacity;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanBuffer *vertexUBO;
|
|
|
|
VulkanBuffer *fragmentUBO;
|
2020-12-21 21:02:07 +00:00
|
|
|
uint32_t minUBOAlignment;
|
|
|
|
|
|
|
|
uint32_t vertexUBOOffset;
|
2020-12-23 21:11:09 +00:00
|
|
|
VkDeviceSize vertexUBOBlockIncrement;
|
2020-12-21 21:02:07 +00:00
|
|
|
|
|
|
|
uint32_t fragmentUBOOffset;
|
2020-12-23 21:11:09 +00:00
|
|
|
VkDeviceSize fragmentUBOBlockIncrement;
|
2020-12-21 21:02:07 +00:00
|
|
|
|
|
|
|
uint32_t frameIndex;
|
2020-12-19 04:08:07 +00:00
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
SDL_mutex *allocatorLock;
|
2020-12-19 00:39:03 +00:00
|
|
|
SDL_mutex *commandLock;
|
2020-12-18 22:35:33 +00:00
|
|
|
|
2020-12-17 02:38:22 +00:00
|
|
|
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
|
|
|
vkfntype_##func func;
|
|
|
|
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
|
|
|
|
vkfntype_##func func;
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
2020-12-17 03:28:02 +00:00
|
|
|
} VulkanRenderer;
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* Forward declarations */
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer);
|
|
|
|
|
|
|
|
/* Macros */
|
|
|
|
|
|
|
|
#define RECORD_CMD(cmdCall) \
|
|
|
|
SDL_LockMutex(renderer->commandLock); \
|
|
|
|
if (renderer->currentCommandBuffer == NULL) \
|
|
|
|
{ \
|
|
|
|
VULKAN_INTERNAL_BeginCommandBuffer(renderer); \
|
|
|
|
} \
|
|
|
|
cmdCall; \
|
|
|
|
renderer->numActiveCommands += 1; \
|
|
|
|
SDL_UnlockMutex(renderer->commandLock);
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
/* Error Handling */
|
|
|
|
|
|
|
|
static inline const char* VkErrorMessages(VkResult code)
|
|
|
|
{
|
|
|
|
#define ERR_TO_STR(e) \
|
|
|
|
case e: return #e;
|
|
|
|
switch (code)
|
|
|
|
{
|
|
|
|
ERR_TO_STR(VK_ERROR_OUT_OF_HOST_MEMORY)
|
|
|
|
ERR_TO_STR(VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
|
|
|
ERR_TO_STR(VK_ERROR_FRAGMENTED_POOL)
|
|
|
|
ERR_TO_STR(VK_ERROR_OUT_OF_POOL_MEMORY)
|
|
|
|
ERR_TO_STR(VK_ERROR_INITIALIZATION_FAILED)
|
|
|
|
ERR_TO_STR(VK_ERROR_LAYER_NOT_PRESENT)
|
|
|
|
ERR_TO_STR(VK_ERROR_EXTENSION_NOT_PRESENT)
|
|
|
|
ERR_TO_STR(VK_ERROR_FEATURE_NOT_PRESENT)
|
|
|
|
ERR_TO_STR(VK_ERROR_TOO_MANY_OBJECTS)
|
|
|
|
ERR_TO_STR(VK_ERROR_DEVICE_LOST)
|
|
|
|
ERR_TO_STR(VK_ERROR_INCOMPATIBLE_DRIVER)
|
|
|
|
ERR_TO_STR(VK_ERROR_OUT_OF_DATE_KHR)
|
|
|
|
ERR_TO_STR(VK_ERROR_SURFACE_LOST_KHR)
|
|
|
|
ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
|
|
|
|
ERR_TO_STR(VK_SUBOPTIMAL_KHR)
|
|
|
|
default: return "Unhandled VkResult!";
|
|
|
|
}
|
|
|
|
#undef ERR_TO_STR
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void LogVulkanResult(
|
|
|
|
const char* vulkanFunctionName,
|
|
|
|
VkResult result
|
|
|
|
) {
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"%s: %s",
|
|
|
|
vulkanFunctionName,
|
|
|
|
VkErrorMessages(result)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2020-12-17 01:23:49 +00:00
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
/* Utility */
|
|
|
|
|
|
|
|
static inline uint8_t DepthFormatContainsStencil(VkFormat format)
|
|
|
|
{
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case VK_FORMAT_D16_UNORM:
|
|
|
|
case VK_FORMAT_D32_SFLOAT:
|
|
|
|
return 0;
|
|
|
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
|
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
|
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
SDL_assert(0 && "Invalid depth format");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Memory Management */
|
|
|
|
|
|
|
|
static inline VkDeviceSize VULKAN_INTERNAL_NextHighestAlignment(
|
|
|
|
VkDeviceSize n,
|
|
|
|
VkDeviceSize align
|
|
|
|
) {
|
|
|
|
return align * ((n + align - 1) / align);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VulkanMemoryFreeRegion* VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
VulkanMemoryAllocation *allocation,
|
|
|
|
VkDeviceSize offset,
|
|
|
|
VkDeviceSize size
|
|
|
|
) {
|
|
|
|
VulkanMemoryFreeRegion *newFreeRegion;
|
|
|
|
uint32_t insertionIndex = 0;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
/* TODO: an improvement here could be to merge contiguous free regions */
|
|
|
|
allocation->freeRegionCount += 1;
|
|
|
|
if (allocation->freeRegionCount > allocation->freeRegionCapacity)
|
|
|
|
{
|
|
|
|
allocation->freeRegionCapacity *= 2;
|
|
|
|
allocation->freeRegions = SDL_realloc(
|
|
|
|
allocation->freeRegions,
|
|
|
|
sizeof(VulkanMemoryFreeRegion*) * allocation->freeRegionCapacity
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
newFreeRegion = SDL_malloc(sizeof(VulkanMemoryFreeRegion));
|
|
|
|
newFreeRegion->offset = offset;
|
|
|
|
newFreeRegion->size = size;
|
|
|
|
newFreeRegion->allocation = allocation;
|
|
|
|
|
|
|
|
allocation->freeRegions[allocation->freeRegionCount - 1] = newFreeRegion;
|
|
|
|
newFreeRegion->allocationIndex = allocation->freeRegionCount - 1;
|
|
|
|
|
|
|
|
for (i = 0; i < allocation->allocator->sortedFreeRegionCount; i += 1)
|
|
|
|
{
|
|
|
|
if (allocation->allocator->sortedFreeRegions[i]->size < size)
|
|
|
|
{
|
|
|
|
/* this is where the new region should go */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
insertionIndex += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allocation->allocator->sortedFreeRegionCount + 1 > allocation->allocator->sortedFreeRegionCapacity)
|
|
|
|
{
|
|
|
|
allocation->allocator->sortedFreeRegionCapacity *= 2;
|
|
|
|
allocation->allocator->sortedFreeRegions = SDL_realloc(
|
|
|
|
allocation->allocator->sortedFreeRegions,
|
|
|
|
sizeof(VulkanMemoryFreeRegion*) * allocation->allocator->sortedFreeRegionCapacity
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* perform insertion sort */
|
|
|
|
if (allocation->allocator->sortedFreeRegionCount > 0 && insertionIndex != allocation->allocator->sortedFreeRegionCount)
|
|
|
|
{
|
|
|
|
for (i = allocation->allocator->sortedFreeRegionCount; i > insertionIndex && i > 0; i -= 1)
|
|
|
|
{
|
|
|
|
allocation->allocator->sortedFreeRegions[i] = allocation->allocator->sortedFreeRegions[i - 1];
|
|
|
|
allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allocation->allocator->sortedFreeRegionCount += 1;
|
|
|
|
allocation->allocator->sortedFreeRegions[insertionIndex] = newFreeRegion;
|
|
|
|
newFreeRegion->sortedIndex = insertionIndex;
|
|
|
|
|
|
|
|
return newFreeRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
|
|
|
|
VulkanMemoryFreeRegion *freeRegion
|
|
|
|
) {
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
/* close the gap in the sorted list */
|
|
|
|
if (freeRegion->allocation->allocator->sortedFreeRegionCount > 1)
|
|
|
|
{
|
|
|
|
for (i = freeRegion->sortedIndex; i < freeRegion->allocation->allocator->sortedFreeRegionCount - 1; i += 1)
|
|
|
|
{
|
|
|
|
freeRegion->allocation->allocator->sortedFreeRegions[i] =
|
|
|
|
freeRegion->allocation->allocator->sortedFreeRegions[i + 1];
|
|
|
|
|
|
|
|
freeRegion->allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
freeRegion->allocation->allocator->sortedFreeRegionCount -= 1;
|
|
|
|
|
|
|
|
/* close the gap in the buffer list */
|
|
|
|
if (freeRegion->allocation->freeRegionCount > 1 && freeRegion->allocationIndex != freeRegion->allocation->freeRegionCount - 1)
|
|
|
|
{
|
|
|
|
freeRegion->allocation->freeRegions[freeRegion->allocationIndex] =
|
|
|
|
freeRegion->allocation->freeRegions[freeRegion->allocation->freeRegionCount - 1];
|
|
|
|
|
|
|
|
freeRegion->allocation->freeRegions[freeRegion->allocationIndex]->allocationIndex =
|
|
|
|
freeRegion->allocationIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
freeRegion->allocation->freeRegionCount -= 1;
|
|
|
|
|
|
|
|
SDL_free(freeRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_FindMemoryType(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
uint32_t typeFilter,
|
|
|
|
VkMemoryPropertyFlags properties,
|
|
|
|
uint32_t *result
|
|
|
|
) {
|
|
|
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
renderer->vkGetPhysicalDeviceMemoryProperties(
|
|
|
|
renderer->physicalDevice,
|
|
|
|
&memoryProperties
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < memoryProperties.memoryTypeCount; i += 1)
|
|
|
|
{
|
|
|
|
if ( (typeFilter & (1 << i)) &&
|
|
|
|
(memoryProperties.memoryTypes[i].propertyFlags & properties) == properties )
|
|
|
|
{
|
|
|
|
*result = i;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
REFRESH_LogError("Failed to find memory properties %X, filter %X", properties, typeFilter);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_FindBufferMemoryRequirements(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkBuffer buffer,
|
|
|
|
VkMemoryRequirements2KHR *pMemoryRequirements,
|
|
|
|
uint32_t *pMemoryTypeIndex
|
|
|
|
) {
|
|
|
|
VkBufferMemoryRequirementsInfo2KHR bufferRequirementsInfo;
|
|
|
|
bufferRequirementsInfo.sType =
|
|
|
|
VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR;
|
|
|
|
bufferRequirementsInfo.pNext = NULL;
|
|
|
|
bufferRequirementsInfo.buffer = buffer;
|
|
|
|
|
|
|
|
renderer->vkGetBufferMemoryRequirements2KHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&bufferRequirementsInfo,
|
|
|
|
pMemoryRequirements
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_FindMemoryType(
|
|
|
|
renderer,
|
|
|
|
pMemoryRequirements->memoryRequirements.memoryTypeBits,
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
|
|
pMemoryTypeIndex
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"Could not find valid memory type for buffer creation"
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_FindImageMemoryRequirements(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkImage image,
|
|
|
|
VkMemoryRequirements2KHR *pMemoryRequirements,
|
|
|
|
uint32_t *pMemoryTypeIndex
|
|
|
|
) {
|
|
|
|
VkImageMemoryRequirementsInfo2KHR imageRequirementsInfo;
|
|
|
|
imageRequirementsInfo.sType =
|
|
|
|
VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR;
|
|
|
|
imageRequirementsInfo.pNext = NULL;
|
|
|
|
imageRequirementsInfo.image = image;
|
|
|
|
|
|
|
|
renderer->vkGetImageMemoryRequirements2KHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageRequirementsInfo,
|
|
|
|
pMemoryRequirements
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_FindMemoryType(
|
|
|
|
renderer,
|
|
|
|
pMemoryRequirements->memoryRequirements.memoryTypeBits,
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
|
|
|
pMemoryTypeIndex
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"Could not find valid memory type for image creation"
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_AllocateMemory(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkBuffer buffer,
|
|
|
|
VkImage image,
|
|
|
|
uint32_t memoryTypeIndex,
|
|
|
|
VkDeviceSize allocationSize,
|
|
|
|
uint8_t dedicated,
|
|
|
|
VulkanMemoryAllocation **pMemoryAllocation
|
|
|
|
) {
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VulkanMemorySubAllocator *allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
|
|
|
|
VkMemoryAllocateInfo allocInfo;
|
|
|
|
VkMemoryDedicatedAllocateInfoKHR dedicatedInfo;
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
allocInfo.memoryTypeIndex = memoryTypeIndex;
|
|
|
|
allocInfo.allocationSize = allocationSize;
|
|
|
|
|
|
|
|
allocation = SDL_malloc(sizeof(VulkanMemoryAllocation));
|
|
|
|
allocation->size = allocationSize;
|
|
|
|
|
|
|
|
if (dedicated)
|
|
|
|
{
|
|
|
|
dedicatedInfo.sType =
|
|
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
|
|
|
|
dedicatedInfo.pNext = NULL;
|
|
|
|
dedicatedInfo.buffer = buffer;
|
|
|
|
dedicatedInfo.image = image;
|
|
|
|
|
|
|
|
allocInfo.pNext = &dedicatedInfo;
|
|
|
|
|
|
|
|
allocation->dedicated = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocInfo.pNext = NULL;
|
|
|
|
|
|
|
|
/* allocate a non-dedicated texture buffer */
|
|
|
|
allocator->allocationCount += 1;
|
|
|
|
allocator->allocations = SDL_realloc(
|
|
|
|
allocator->allocations,
|
|
|
|
sizeof(VulkanMemoryAllocation*) * allocator->allocationCount
|
|
|
|
);
|
|
|
|
|
|
|
|
allocator->allocations[
|
|
|
|
allocator->allocationCount - 1
|
|
|
|
] = allocation;
|
|
|
|
|
|
|
|
allocation->dedicated = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
allocation->freeRegions = SDL_malloc(sizeof(VulkanMemoryFreeRegion*));
|
|
|
|
allocation->freeRegionCount = 0;
|
|
|
|
allocation->freeRegionCapacity = 1;
|
|
|
|
allocation->allocator = allocator;
|
|
|
|
|
|
|
|
result = renderer->vkAllocateMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&allocInfo,
|
|
|
|
NULL,
|
|
|
|
&allocation->memory
|
|
|
|
);
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkAllocateMemory", result);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
allocation,
|
|
|
|
0,
|
|
|
|
allocation->size
|
|
|
|
);
|
|
|
|
|
|
|
|
*pMemoryAllocation = allocation;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_FindAvailableMemory(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkBuffer buffer,
|
|
|
|
VkImage image,
|
|
|
|
VulkanMemoryAllocation **pMemoryAllocation,
|
|
|
|
VkDeviceSize *pOffset,
|
|
|
|
VkDeviceSize *pSize
|
|
|
|
) {
|
|
|
|
VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
|
|
|
|
{
|
|
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
VkMemoryRequirements2KHR memoryRequirements =
|
|
|
|
{
|
|
|
|
VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
|
|
|
|
&dedicatedRequirements
|
|
|
|
};
|
|
|
|
uint32_t memoryTypeIndex;
|
|
|
|
|
|
|
|
VulkanMemoryAllocation *allocation;
|
|
|
|
VulkanMemorySubAllocator *allocator;
|
|
|
|
VulkanMemoryFreeRegion *region;
|
|
|
|
|
|
|
|
VkDeviceSize requiredSize, allocationSize;
|
|
|
|
VkDeviceSize alignedOffset;
|
2020-12-21 20:37:54 +00:00
|
|
|
VkDeviceSize newRegionSize, newRegionOffset;
|
2020-12-18 22:35:33 +00:00
|
|
|
uint8_t allocationResult;
|
|
|
|
|
|
|
|
if (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Calling FindAvailableMemory with both a buffer and image handle is invalid!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (buffer != VK_NULL_HANDLE)
|
|
|
|
{
|
|
|
|
if (!VULKAN_INTERNAL_FindBufferMemoryRequirements(
|
|
|
|
renderer,
|
|
|
|
buffer,
|
|
|
|
&memoryRequirements,
|
|
|
|
&memoryTypeIndex
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to acquire buffer memory requirements!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (image != VK_NULL_HANDLE)
|
|
|
|
{
|
|
|
|
if (!VULKAN_INTERNAL_FindImageMemoryRequirements(
|
|
|
|
renderer,
|
|
|
|
image,
|
|
|
|
&memoryRequirements,
|
|
|
|
&memoryTypeIndex
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to acquire image memory requirements!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Calling FindAvailableMemory with neither buffer nor image handle is invalid!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
|
|
|
|
requiredSize = memoryRequirements.memoryRequirements.size;
|
|
|
|
|
|
|
|
SDL_LockMutex(renderer->allocatorLock);
|
|
|
|
|
|
|
|
/* find the largest free region and use it */
|
|
|
|
if (allocator->sortedFreeRegionCount > 0)
|
|
|
|
{
|
|
|
|
region = allocator->sortedFreeRegions[0];
|
|
|
|
allocation = region->allocation;
|
|
|
|
|
|
|
|
alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
|
|
|
|
region->offset,
|
|
|
|
memoryRequirements.memoryRequirements.alignment
|
|
|
|
);
|
|
|
|
|
|
|
|
if (alignedOffset + requiredSize <= region->offset + region->size)
|
|
|
|
{
|
|
|
|
*pMemoryAllocation = allocation;
|
|
|
|
|
|
|
|
/* not aligned - create a new free region */
|
|
|
|
if (region->offset != alignedOffset)
|
|
|
|
{
|
|
|
|
VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
allocation,
|
|
|
|
region->offset,
|
|
|
|
alignedOffset - region->offset
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pOffset = alignedOffset;
|
|
|
|
*pSize = requiredSize;
|
|
|
|
|
|
|
|
newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
|
|
|
|
newRegionOffset = alignedOffset + requiredSize;
|
|
|
|
|
|
|
|
/* remove and add modified region to re-sort */
|
|
|
|
VULKAN_INTERNAL_RemoveMemoryFreeRegion(region);
|
|
|
|
|
|
|
|
/* if size is 0, no need to re-insert */
|
|
|
|
if (newRegionSize != 0)
|
|
|
|
{
|
|
|
|
VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
allocation,
|
|
|
|
newRegionOffset,
|
|
|
|
newRegionSize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No suitable free regions exist, allocate a new memory region */
|
|
|
|
|
|
|
|
if (dedicatedRequirements.prefersDedicatedAllocation || dedicatedRequirements.requiresDedicatedAllocation)
|
|
|
|
{
|
|
|
|
allocationSize = requiredSize;
|
|
|
|
}
|
|
|
|
else if (requiredSize > allocator->nextAllocationSize)
|
|
|
|
{
|
|
|
|
/* allocate a page of required size aligned to STARTING_ALLOCATION_SIZE increments */
|
|
|
|
allocationSize =
|
|
|
|
VULKAN_INTERNAL_NextHighestAlignment(requiredSize, STARTING_ALLOCATION_SIZE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocationSize = allocator->nextAllocationSize;
|
|
|
|
allocator->nextAllocationSize = SDL_min(allocator->nextAllocationSize * 2, MAX_ALLOCATION_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
allocationResult = VULKAN_INTERNAL_AllocateMemory(
|
|
|
|
renderer,
|
|
|
|
buffer,
|
|
|
|
image,
|
|
|
|
memoryTypeIndex,
|
|
|
|
allocationSize,
|
|
|
|
dedicatedRequirements.prefersDedicatedAllocation || dedicatedRequirements.requiresDedicatedAllocation,
|
|
|
|
&allocation
|
|
|
|
);
|
2020-12-17 04:04:47 +00:00
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
/* Uh oh, we're out of memory */
|
|
|
|
if (allocationResult == 0)
|
|
|
|
{
|
|
|
|
/* Responsibility of the caller to handle being out of memory */
|
|
|
|
REFRESH_LogWarn("Failed to allocate memory!");
|
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pMemoryAllocation = allocation;
|
|
|
|
*pOffset = 0;
|
|
|
|
*pSize = requiredSize;
|
|
|
|
|
|
|
|
region = allocation->freeRegions[0];
|
|
|
|
|
|
|
|
newRegionOffset = region->offset + requiredSize;
|
|
|
|
newRegionSize = region->size - requiredSize;
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_RemoveMemoryFreeRegion(region);
|
|
|
|
|
|
|
|
if (newRegionSize != 0)
|
|
|
|
{
|
|
|
|
VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
allocation,
|
|
|
|
newRegionOffset,
|
|
|
|
newRegionSize
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* Memory Barriers */
|
|
|
|
|
2020-12-19 01:03:26 +00:00
|
|
|
static void VULKAN_INTERNAL_BufferMemoryBarrier(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VulkanResourceAccessType nextResourceAccessType,
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanBuffer *buffer,
|
|
|
|
VulkanSubBuffer *subBuffer
|
2020-12-19 01:03:26 +00:00
|
|
|
) {
|
|
|
|
VkPipelineStageFlags srcStages = 0;
|
|
|
|
VkPipelineStageFlags dstStages = 0;
|
|
|
|
VkBufferMemoryBarrier memoryBarrier;
|
|
|
|
VulkanResourceAccessType prevAccess, nextAccess;
|
|
|
|
const VulkanResourceAccessInfo *prevAccessInfo, *nextAccessInfo;
|
|
|
|
|
|
|
|
if (buffer->resourceAccessType == nextResourceAccessType)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
|
|
|
memoryBarrier.pNext = NULL;
|
|
|
|
memoryBarrier.srcAccessMask = 0;
|
|
|
|
memoryBarrier.dstAccessMask = 0;
|
|
|
|
memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
2020-12-19 04:08:07 +00:00
|
|
|
memoryBarrier.buffer = subBuffer->buffer;
|
2020-12-19 01:03:26 +00:00
|
|
|
memoryBarrier.offset = 0;
|
|
|
|
memoryBarrier.size = buffer->size;
|
|
|
|
|
|
|
|
prevAccess = buffer->resourceAccessType;
|
|
|
|
prevAccessInfo = &AccessMap[prevAccess];
|
|
|
|
|
|
|
|
srcStages |= prevAccessInfo->stageMask;
|
|
|
|
|
|
|
|
if (prevAccess > RESOURCE_ACCESS_END_OF_READ)
|
|
|
|
{
|
|
|
|
memoryBarrier.srcAccessMask |= prevAccessInfo->accessMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
nextAccess = nextResourceAccessType;
|
|
|
|
nextAccessInfo = &AccessMap[nextAccess];
|
|
|
|
|
|
|
|
dstStages |= nextAccessInfo->stageMask;
|
|
|
|
|
|
|
|
if (memoryBarrier.srcAccessMask != 0)
|
|
|
|
{
|
|
|
|
memoryBarrier.dstAccessMask |= nextAccessInfo->accessMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (srcStages == 0)
|
|
|
|
{
|
|
|
|
srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
|
}
|
|
|
|
if (dstStages == 0)
|
|
|
|
{
|
|
|
|
dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdPipelineBarrier(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
srcStages,
|
|
|
|
dstStages,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
1,
|
|
|
|
&memoryBarrier,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
));
|
|
|
|
|
|
|
|
buffer->resourceAccessType = nextResourceAccessType;
|
|
|
|
}
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
static void VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VulkanResourceAccessType nextAccess,
|
|
|
|
VkImageAspectFlags aspectMask,
|
|
|
|
uint32_t baseLayer,
|
|
|
|
uint32_t layerCount,
|
|
|
|
uint32_t baseLevel,
|
|
|
|
uint32_t levelCount,
|
|
|
|
uint8_t discardContents,
|
|
|
|
VkImage image,
|
|
|
|
VulkanResourceAccessType *resourceAccessType
|
|
|
|
) {
|
|
|
|
VkPipelineStageFlags srcStages = 0;
|
|
|
|
VkPipelineStageFlags dstStages = 0;
|
|
|
|
VkImageMemoryBarrier memoryBarrier;
|
|
|
|
VulkanResourceAccessType prevAccess;
|
|
|
|
const VulkanResourceAccessInfo *pPrevAccessInfo, *pNextAccessInfo;
|
|
|
|
|
|
|
|
if (*resourceAccessType == nextAccess)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
memoryBarrier.pNext = NULL;
|
|
|
|
memoryBarrier.srcAccessMask = 0;
|
|
|
|
memoryBarrier.dstAccessMask = 0;
|
|
|
|
memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
memoryBarrier.image = image;
|
|
|
|
memoryBarrier.subresourceRange.aspectMask = aspectMask;
|
|
|
|
memoryBarrier.subresourceRange.baseArrayLayer = baseLayer;
|
|
|
|
memoryBarrier.subresourceRange.layerCount = layerCount;
|
|
|
|
memoryBarrier.subresourceRange.baseMipLevel = baseLevel;
|
|
|
|
memoryBarrier.subresourceRange.levelCount = levelCount;
|
|
|
|
|
|
|
|
prevAccess = *resourceAccessType;
|
|
|
|
pPrevAccessInfo = &AccessMap[prevAccess];
|
|
|
|
|
|
|
|
srcStages |= pPrevAccessInfo->stageMask;
|
|
|
|
|
|
|
|
if (prevAccess > RESOURCE_ACCESS_END_OF_READ)
|
|
|
|
{
|
|
|
|
memoryBarrier.srcAccessMask |= pPrevAccessInfo->accessMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (discardContents)
|
|
|
|
{
|
|
|
|
memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memoryBarrier.oldLayout = pPrevAccessInfo->imageLayout;
|
|
|
|
}
|
|
|
|
|
|
|
|
pNextAccessInfo = &AccessMap[nextAccess];
|
|
|
|
|
|
|
|
dstStages |= pNextAccessInfo->stageMask;
|
|
|
|
|
|
|
|
memoryBarrier.dstAccessMask |= pNextAccessInfo->accessMask;
|
|
|
|
memoryBarrier.newLayout = pNextAccessInfo->imageLayout;
|
|
|
|
|
|
|
|
if (srcStages == 0)
|
|
|
|
{
|
|
|
|
srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
|
}
|
|
|
|
if (dstStages == 0)
|
|
|
|
{
|
|
|
|
dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdPipelineBarrier(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
srcStages,
|
|
|
|
dstStages,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
1,
|
|
|
|
&memoryBarrier
|
|
|
|
));
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
*resourceAccessType = nextAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Resource Disposal */
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_DestroyBuffer(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VulkanBuffer *buffer
|
|
|
|
) {
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
if (buffer->bound || buffer->boundSubmitted)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Cannot destroy a bound buffer!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < buffer->subBufferCount; i += 1)
|
|
|
|
{
|
|
|
|
if (buffer->subBuffers[i]->allocation->dedicated)
|
|
|
|
{
|
|
|
|
renderer->vkFreeMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
buffer->subBuffers[i]->allocation->memory,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_free(buffer->subBuffers[i]->allocation->freeRegions);
|
|
|
|
SDL_free(buffer->subBuffers[i]->allocation);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_LockMutex(renderer->allocatorLock);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_NewMemoryFreeRegion(
|
|
|
|
buffer->subBuffers[i]->allocation,
|
|
|
|
buffer->subBuffers[i]->offset,
|
|
|
|
buffer->subBuffers[i]->size
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_UnlockMutex(renderer->allocatorLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkDestroyBuffer(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
buffer->subBuffers[i]->buffer,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_free(buffer->subBuffers[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_free(buffer->subBuffers);
|
|
|
|
buffer->subBuffers = NULL;
|
|
|
|
|
|
|
|
SDL_free(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_DestroySwapchain(VulkanRenderer* renderer)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < renderer->swapChainImageCount; i += 1)
|
|
|
|
{
|
|
|
|
renderer->vkDestroyImageView(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->swapChainImageViews[i],
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_free(renderer->swapChainImages);
|
|
|
|
renderer->swapChainImages = NULL;
|
|
|
|
SDL_free(renderer->swapChainImageViews);
|
|
|
|
renderer->swapChainImageViews = NULL;
|
|
|
|
SDL_free(renderer->swapChainResourceAccessTypes);
|
|
|
|
renderer->swapChainResourceAccessTypes = NULL;
|
|
|
|
|
|
|
|
renderer->vkDestroySwapchainKHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->swapChain,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_PerformDeferredDestroys(VulkanRenderer* renderer)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Swapchain */
|
|
|
|
|
|
|
|
static inline VkExtent2D VULKAN_INTERNAL_ChooseSwapExtent(
|
|
|
|
void* windowHandle,
|
|
|
|
const VkSurfaceCapabilitiesKHR capabilities
|
|
|
|
) {
|
|
|
|
VkExtent2D actualExtent;
|
|
|
|
int32_t drawableWidth, drawableHeight;
|
|
|
|
|
|
|
|
if (capabilities.currentExtent.width != UINT32_MAX)
|
|
|
|
{
|
|
|
|
return capabilities.currentExtent;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_Vulkan_GetDrawableSize(
|
|
|
|
(SDL_Window*) windowHandle,
|
|
|
|
&drawableWidth,
|
|
|
|
&drawableHeight
|
|
|
|
);
|
|
|
|
|
|
|
|
actualExtent.width = drawableWidth;
|
|
|
|
actualExtent.height = drawableHeight;
|
|
|
|
|
|
|
|
return actualExtent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_QuerySwapChainSupport(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkPhysicalDevice physicalDevice,
|
|
|
|
VkSurfaceKHR surface,
|
|
|
|
SwapChainSupportDetails *outputDetails
|
|
|
|
) {
|
|
|
|
VkResult result;
|
|
|
|
uint32_t formatCount;
|
|
|
|
uint32_t presentModeCount;
|
|
|
|
|
|
|
|
result = renderer->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&outputDetails->capabilities
|
|
|
|
);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR: %s",
|
|
|
|
VkErrorMessages(result)
|
|
|
|
);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&formatCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
if (formatCount != 0)
|
|
|
|
{
|
|
|
|
outputDetails->formats = (VkSurfaceFormatKHR*) SDL_malloc(
|
|
|
|
sizeof(VkSurfaceFormatKHR) * formatCount
|
|
|
|
);
|
|
|
|
outputDetails->formatsLength = formatCount;
|
|
|
|
|
|
|
|
if (!outputDetails->formats)
|
|
|
|
{
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&formatCount,
|
|
|
|
outputDetails->formats
|
|
|
|
);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkGetPhysicalDeviceSurfaceFormatsKHR: %s",
|
|
|
|
VkErrorMessages(result)
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_free(outputDetails->formats);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&presentModeCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
if (presentModeCount != 0)
|
|
|
|
{
|
|
|
|
outputDetails->presentModes = (VkPresentModeKHR*) SDL_malloc(
|
|
|
|
sizeof(VkPresentModeKHR) * presentModeCount
|
|
|
|
);
|
|
|
|
outputDetails->presentModesLength = presentModeCount;
|
|
|
|
|
|
|
|
if (!outputDetails->presentModes)
|
|
|
|
{
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&presentModeCount,
|
|
|
|
outputDetails->presentModes
|
|
|
|
);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkGetPhysicalDeviceSurfacePresentModesKHR: %s",
|
|
|
|
VkErrorMessages(result)
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_free(outputDetails->formats);
|
|
|
|
SDL_free(outputDetails->presentModes);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_ChooseSwapSurfaceFormat(
|
|
|
|
VkFormat desiredFormat,
|
|
|
|
VkSurfaceFormatKHR *availableFormats,
|
|
|
|
uint32_t availableFormatsLength,
|
|
|
|
VkSurfaceFormatKHR *outputFormat
|
|
|
|
) {
|
|
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < availableFormatsLength; i += 1)
|
|
|
|
{
|
|
|
|
if ( availableFormats[i].format == desiredFormat &&
|
|
|
|
availableFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR )
|
|
|
|
{
|
|
|
|
*outputFormat = availableFormats[i];
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
REFRESH_LogError("Desired surface format is unavailable.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_ChooseSwapPresentMode(
|
|
|
|
REFRESH_PresentMode desiredPresentInterval,
|
|
|
|
VkPresentModeKHR *availablePresentModes,
|
|
|
|
uint32_t availablePresentModesLength,
|
|
|
|
VkPresentModeKHR *outputPresentMode
|
|
|
|
) {
|
|
|
|
#define CHECK_MODE(m) \
|
|
|
|
for (i = 0; i < availablePresentModesLength; i += 1) \
|
|
|
|
{ \
|
|
|
|
if (availablePresentModes[i] == m) \
|
|
|
|
{ \
|
|
|
|
*outputPresentMode = m; \
|
|
|
|
REFRESH_LogInfo("Using " #m "!"); \
|
|
|
|
return 1; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
REFRESH_LogInfo(#m " unsupported.");
|
|
|
|
|
|
|
|
uint32_t i;
|
|
|
|
if (desiredPresentInterval == REFRESH_PRESENTMODE_IMMEDIATE)
|
|
|
|
{
|
|
|
|
CHECK_MODE(VK_PRESENT_MODE_IMMEDIATE_KHR)
|
|
|
|
}
|
|
|
|
else if (desiredPresentInterval == REFRESH_PRESENTMODE_MAILBOX)
|
|
|
|
{
|
|
|
|
CHECK_MODE(VK_PRESENT_MODE_MAILBOX_KHR)
|
|
|
|
}
|
|
|
|
else if (desiredPresentInterval == REFRESH_PRESENTMODE_FIFO)
|
|
|
|
{
|
|
|
|
CHECK_MODE(VK_PRESENT_MODE_FIFO_KHR)
|
|
|
|
}
|
|
|
|
else if (desiredPresentInterval == REFRESH_PRESENTMODE_FIFO_RELAXED)
|
|
|
|
{
|
|
|
|
CHECK_MODE(VK_PRESENT_MODE_FIFO_RELAXED_KHR)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"Unrecognized PresentInterval: %d",
|
|
|
|
desiredPresentInterval
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef CHECK_MODE
|
|
|
|
|
|
|
|
REFRESH_LogInfo("Fall back to VK_PRESENT_MODE_FIFO_KHR.");
|
|
|
|
*outputPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CreateSwapchainResult VULKAN_INTERNAL_CreateSwapchain(
|
|
|
|
VulkanRenderer *renderer
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
SwapChainSupportDetails swapChainSupportDetails;
|
|
|
|
VkSurfaceFormatKHR surfaceFormat;
|
|
|
|
VkPresentModeKHR presentMode;
|
|
|
|
VkExtent2D extent;
|
|
|
|
uint32_t imageCount, swapChainImageCount, i;
|
|
|
|
VkSwapchainCreateInfoKHR swapChainCreateInfo;
|
|
|
|
VkImage *swapChainImages;
|
|
|
|
VkImageViewCreateInfo createInfo;
|
|
|
|
VkImageView swapChainImageView;
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_QuerySwapChainSupport(
|
|
|
|
renderer,
|
|
|
|
renderer->physicalDevice,
|
|
|
|
renderer->surface,
|
|
|
|
&swapChainSupportDetails
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Device does not support swap chain creation");
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->swapChainFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
|
|
|
renderer->swapChainSwizzle.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
renderer->swapChainSwizzle.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
renderer->swapChainSwizzle.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
renderer->swapChainSwizzle.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
if (!VULKAN_INTERNAL_ChooseSwapSurfaceFormat(
|
|
|
|
renderer->swapChainFormat,
|
|
|
|
swapChainSupportDetails.formats,
|
|
|
|
swapChainSupportDetails.formatsLength,
|
|
|
|
&surfaceFormat
|
|
|
|
)) {
|
|
|
|
SDL_free(swapChainSupportDetails.formats);
|
|
|
|
SDL_free(swapChainSupportDetails.presentModes);
|
|
|
|
REFRESH_LogError("Device does not support swap chain format");
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_ChooseSwapPresentMode(
|
|
|
|
renderer->presentMode,
|
|
|
|
swapChainSupportDetails.presentModes,
|
|
|
|
swapChainSupportDetails.presentModesLength,
|
|
|
|
&presentMode
|
|
|
|
)) {
|
|
|
|
SDL_free(swapChainSupportDetails.formats);
|
|
|
|
SDL_free(swapChainSupportDetails.presentModes);
|
|
|
|
REFRESH_LogError("Device does not support swap chain present mode");
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extent = VULKAN_INTERNAL_ChooseSwapExtent(
|
|
|
|
renderer->deviceWindowHandle,
|
|
|
|
swapChainSupportDetails.capabilities
|
|
|
|
);
|
|
|
|
|
|
|
|
if (extent.width == 0 || extent.height == 0)
|
|
|
|
{
|
|
|
|
return CREATE_SWAPCHAIN_SURFACE_ZERO;
|
|
|
|
}
|
|
|
|
|
|
|
|
imageCount = swapChainSupportDetails.capabilities.minImageCount + 1;
|
|
|
|
|
|
|
|
if ( swapChainSupportDetails.capabilities.maxImageCount > 0 &&
|
|
|
|
imageCount > swapChainSupportDetails.capabilities.maxImageCount )
|
|
|
|
{
|
|
|
|
imageCount = swapChainSupportDetails.capabilities.maxImageCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
|
|
|
{
|
|
|
|
/* Required for proper triple-buffering.
|
|
|
|
* Note that this is below the above maxImageCount check!
|
|
|
|
* If the driver advertises MAILBOX but does not support 3 swap
|
|
|
|
* images, it's not real mailbox support, so let it fail hard.
|
|
|
|
* -flibit
|
|
|
|
*/
|
|
|
|
imageCount = SDL_max(imageCount, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
|
|
swapChainCreateInfo.pNext = NULL;
|
|
|
|
swapChainCreateInfo.flags = 0;
|
|
|
|
swapChainCreateInfo.surface = renderer->surface;
|
|
|
|
swapChainCreateInfo.minImageCount = imageCount;
|
|
|
|
swapChainCreateInfo.imageFormat = surfaceFormat.format;
|
|
|
|
swapChainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
|
|
|
|
swapChainCreateInfo.imageExtent = extent;
|
|
|
|
swapChainCreateInfo.imageArrayLayers = 1;
|
|
|
|
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
|
|
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
swapChainCreateInfo.queueFamilyIndexCount = 0;
|
|
|
|
swapChainCreateInfo.pQueueFamilyIndices = NULL;
|
|
|
|
swapChainCreateInfo.preTransform = swapChainSupportDetails.capabilities.currentTransform;
|
|
|
|
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
|
|
swapChainCreateInfo.presentMode = presentMode;
|
|
|
|
swapChainCreateInfo.clipped = VK_TRUE;
|
|
|
|
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateSwapchainKHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&swapChainCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->swapChain
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_free(swapChainSupportDetails.formats);
|
|
|
|
SDL_free(swapChainSupportDetails.presentModes);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateSwapchainKHR", vulkanResult);
|
|
|
|
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkGetSwapchainImagesKHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->swapChain,
|
|
|
|
&swapChainImageCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->swapChainImages = (VkImage*) SDL_malloc(
|
|
|
|
sizeof(VkImage) * swapChainImageCount
|
|
|
|
);
|
|
|
|
if (!renderer->swapChainImages)
|
|
|
|
{
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->swapChainImageViews = (VkImageView*) SDL_malloc(
|
|
|
|
sizeof(VkImageView) * swapChainImageCount
|
|
|
|
);
|
|
|
|
if (!renderer->swapChainImageViews)
|
|
|
|
{
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->swapChainResourceAccessTypes = (VulkanResourceAccessType*) SDL_malloc(
|
|
|
|
sizeof(VulkanResourceAccessType) * swapChainImageCount
|
|
|
|
);
|
|
|
|
if (!renderer->swapChainResourceAccessTypes)
|
|
|
|
{
|
|
|
|
SDL_OutOfMemory();
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
swapChainImages = SDL_stack_alloc(VkImage, swapChainImageCount);
|
|
|
|
renderer->vkGetSwapchainImagesKHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->swapChain,
|
|
|
|
&swapChainImageCount,
|
|
|
|
swapChainImages
|
|
|
|
);
|
|
|
|
renderer->swapChainImageCount = swapChainImageCount;
|
|
|
|
renderer->swapChainExtent = extent;
|
|
|
|
|
|
|
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
createInfo.pNext = NULL;
|
|
|
|
createInfo.flags = 0;
|
|
|
|
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
createInfo.format = surfaceFormat.format;
|
|
|
|
createInfo.components = renderer->swapChainSwizzle;
|
|
|
|
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
createInfo.subresourceRange.baseMipLevel = 0;
|
|
|
|
createInfo.subresourceRange.levelCount = 1;
|
|
|
|
createInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
|
createInfo.subresourceRange.layerCount = 1;
|
|
|
|
for (i = 0; i < swapChainImageCount; i += 1)
|
|
|
|
{
|
|
|
|
createInfo.image = swapChainImages[i];
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImageView(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&createInfo,
|
|
|
|
NULL,
|
|
|
|
&swapChainImageView
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateImageView", vulkanResult);
|
|
|
|
SDL_stack_free(swapChainImages);
|
|
|
|
return CREATE_SWAPCHAIN_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->swapChainImages[i] = swapChainImages[i];
|
|
|
|
renderer->swapChainImageViews[i] = swapChainImageView;
|
|
|
|
renderer->swapChainResourceAccessTypes[i] = RESOURCE_ACCESS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_stack_free(swapChainImages);
|
|
|
|
return CREATE_SWAPCHAIN_SUCCESS;
|
2020-12-19 00:39:03 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
static void VULKAN_INTERNAL_RecreateSwapchain(VulkanRenderer* renderer)
|
|
|
|
{
|
|
|
|
CreateSwapchainResult createSwapchainResult;
|
|
|
|
SwapChainSupportDetails swapChainSupportDetails;
|
|
|
|
VkExtent2D extent;
|
2020-12-19 04:08:07 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->vkDeviceWaitIdle(renderer->logicalDevice);
|
2020-12-19 04:08:07 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_QuerySwapChainSupport(
|
|
|
|
renderer,
|
|
|
|
renderer->physicalDevice,
|
|
|
|
renderer->surface,
|
|
|
|
&swapChainSupportDetails
|
|
|
|
);
|
|
|
|
|
|
|
|
extent = VULKAN_INTERNAL_ChooseSwapExtent(
|
|
|
|
renderer->deviceWindowHandle,
|
|
|
|
swapChainSupportDetails.capabilities
|
|
|
|
);
|
|
|
|
|
|
|
|
if (extent.width == 0 || extent.height == 0)
|
2020-12-19 04:08:07 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_DestroySwapchain(renderer);
|
|
|
|
createSwapchainResult = VULKAN_INTERNAL_CreateSwapchain(renderer);
|
2020-12-19 04:08:07 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (createSwapchainResult == CREATE_SWAPCHAIN_FAIL)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to recreate swapchain");
|
|
|
|
return;
|
2020-12-19 04:08:07 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->vkDeviceWaitIdle(renderer->logicalDevice);
|
2020-12-19 04:08:07 +00:00
|
|
|
}
|
2020-12-19 01:03:26 +00:00
|
|
|
|
|
|
|
/* Data Buffer */
|
|
|
|
|
|
|
|
/* buffer should be an alloc'd but uninitialized VulkanTexture */
|
|
|
|
static uint8_t VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkDeviceSize size,
|
|
|
|
VulkanResourceAccessType resourceAccessType,
|
|
|
|
VkBufferUsageFlags usage,
|
2020-12-19 04:08:07 +00:00
|
|
|
uint32_t subBufferCount,
|
2020-12-19 01:03:26 +00:00
|
|
|
VulkanBuffer *buffer
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
VkBufferCreateInfo bufferCreateInfo;
|
|
|
|
uint8_t findMemoryResult;
|
2020-12-19 04:08:07 +00:00
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
buffer->size = size;
|
2020-12-23 06:05:01 +00:00
|
|
|
buffer->currentSubBufferIndex = 0;
|
2020-12-19 04:08:07 +00:00
|
|
|
buffer->bound = 0;
|
|
|
|
buffer->boundSubmitted = 0;
|
|
|
|
buffer->resourceAccessType = resourceAccessType;
|
|
|
|
buffer->usage = usage;
|
|
|
|
buffer->subBufferCount = subBufferCount;
|
|
|
|
buffer->subBuffers = SDL_malloc(
|
2020-12-22 01:59:08 +00:00
|
|
|
sizeof(VulkanSubBuffer*) * buffer->subBufferCount
|
2020-12-19 04:08:07 +00:00
|
|
|
);
|
2020-12-19 01:03:26 +00:00
|
|
|
|
|
|
|
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
|
|
bufferCreateInfo.pNext = NULL;
|
|
|
|
bufferCreateInfo.flags = 0;
|
|
|
|
bufferCreateInfo.size = size;
|
|
|
|
bufferCreateInfo.usage = usage;
|
|
|
|
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
bufferCreateInfo.queueFamilyIndexCount = 1;
|
|
|
|
bufferCreateInfo.pQueueFamilyIndices = &renderer->queueFamilyIndices.graphicsFamily;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
for (i = 0; i < subBufferCount; i += 1)
|
2020-12-19 01:03:26 +00:00
|
|
|
{
|
2020-12-22 01:59:08 +00:00
|
|
|
buffer->subBuffers[i] = SDL_malloc(
|
|
|
|
sizeof(VulkanSubBuffer) * buffer->subBufferCount
|
|
|
|
);
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
vulkanResult = renderer->vkCreateBuffer(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&bufferCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&buffer->subBuffers[i]->buffer
|
|
|
|
);
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateBuffer", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create VkBuffer");
|
|
|
|
return 0;
|
|
|
|
}
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
findMemoryResult = VULKAN_INTERNAL_FindAvailableMemory(
|
|
|
|
renderer,
|
|
|
|
buffer->subBuffers[i]->buffer,
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
&buffer->subBuffers[i]->allocation,
|
|
|
|
&buffer->subBuffers[i]->offset,
|
|
|
|
&buffer->subBuffers[i]->size
|
|
|
|
);
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
/* We're out of available memory */
|
|
|
|
if (findMemoryResult == 2)
|
|
|
|
{
|
|
|
|
REFRESH_LogWarn("Out of buffer memory!");
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
else if (findMemoryResult == 0)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to find buffer memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
vulkanResult = renderer->vkBindBufferMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
buffer->subBuffers[i]->buffer,
|
|
|
|
buffer->subBuffers[i]->allocation->memory,
|
|
|
|
buffer->subBuffers[i]->offset
|
|
|
|
);
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to bind buffer memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
2020-12-19 01:03:26 +00:00
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
buffer->subBuffers[i]->resourceAccessType = resourceAccessType;
|
2020-12-23 06:05:01 +00:00
|
|
|
buffer->subBuffers[i]->bound = -1;
|
2020-12-19 04:08:07 +00:00
|
|
|
|
|
|
|
VULKAN_INTERNAL_BufferMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
buffer->resourceAccessType,
|
|
|
|
buffer,
|
|
|
|
buffer->subBuffers[i]
|
|
|
|
);
|
|
|
|
}
|
2020-12-19 01:03:26 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
/* Command Buffers */
|
2020-12-17 04:04:47 +00:00
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer)
|
|
|
|
{
|
|
|
|
VkCommandBufferAllocateInfo allocateInfo;
|
|
|
|
VkCommandBufferBeginInfo beginInfo;
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
|
|
beginInfo.pNext = NULL;
|
|
|
|
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
|
|
beginInfo.pInheritanceInfo = NULL;
|
|
|
|
|
|
|
|
/* If we are out of unused command buffers, allocate some more */
|
|
|
|
if (renderer->inactiveCommandBufferCount == 0)
|
|
|
|
{
|
|
|
|
renderer->activeCommandBuffers = SDL_realloc(
|
|
|
|
renderer->activeCommandBuffers,
|
|
|
|
sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount * 2
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->inactiveCommandBuffers = SDL_realloc(
|
|
|
|
renderer->inactiveCommandBuffers,
|
|
|
|
sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount * 2
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->submittedCommandBuffers = SDL_realloc(
|
|
|
|
renderer->submittedCommandBuffers,
|
|
|
|
sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount * 2
|
|
|
|
);
|
|
|
|
|
|
|
|
allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
|
|
allocateInfo.pNext = NULL;
|
|
|
|
allocateInfo.commandPool = renderer->commandPool;
|
|
|
|
allocateInfo.commandBufferCount = renderer->allocatedCommandBufferCount;
|
|
|
|
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
|
|
|
|
|
|
result = renderer->vkAllocateCommandBuffers(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&allocateInfo,
|
|
|
|
renderer->inactiveCommandBuffers
|
|
|
|
);
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkAllocateCommandBuffers", result);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->inactiveCommandBufferCount = renderer->allocatedCommandBufferCount;
|
|
|
|
renderer->allocatedCommandBufferCount *= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->currentCommandBuffer =
|
|
|
|
renderer->inactiveCommandBuffers[renderer->inactiveCommandBufferCount - 1];
|
|
|
|
|
|
|
|
renderer->activeCommandBuffers[renderer->activeCommandBufferCount] = renderer->currentCommandBuffer;
|
|
|
|
|
|
|
|
renderer->activeCommandBufferCount += 1;
|
|
|
|
renderer->inactiveCommandBufferCount -= 1;
|
|
|
|
|
|
|
|
result = renderer->vkBeginCommandBuffer(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
&beginInfo
|
|
|
|
);
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkBeginCommandBuffer", result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-22 02:34:57 +00:00
|
|
|
static void VULKAN_INTERNAL_EndCommandBuffer(
|
|
|
|
VulkanRenderer* renderer
|
|
|
|
) {
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
result = renderer->vkEndCommandBuffer(
|
|
|
|
renderer->currentCommandBuffer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkEndCommandBuffer", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->currentCommandBuffer = NULL;
|
|
|
|
renderer->numActiveCommands = 0;
|
|
|
|
}
|
|
|
|
|
2020-12-17 04:04:47 +00:00
|
|
|
/* Public API */
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
static void VULKAN_DestroyDevice(
|
|
|
|
REFRESH_Device *device
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_Clear(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_ClearOptions options,
|
|
|
|
REFRESH_Vec4 **colors,
|
|
|
|
uint32_t colorCount,
|
|
|
|
float depth,
|
|
|
|
int32_t stencil
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
static void VULKAN_DrawInstancedPrimitives(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t baseVertex,
|
|
|
|
uint32_t minVertexIndex,
|
|
|
|
uint32_t numVertices,
|
|
|
|
uint32_t startIndex,
|
|
|
|
uint32_t primitiveCount,
|
2020-12-20 09:29:15 +00:00
|
|
|
uint32_t instanceCount,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Buffer *indices,
|
|
|
|
REFRESH_IndexElementSize indexElementSize
|
|
|
|
) {
|
2020-12-20 09:29:15 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VkDescriptorSet descriptorSets[4];
|
|
|
|
uint32_t dynamicOffsets[2];
|
|
|
|
|
2020-12-23 06:56:26 +00:00
|
|
|
descriptorSets[0] = renderer->currentGraphicsPipeline->vertexSamplerDescriptorSet;
|
|
|
|
descriptorSets[1] = renderer->currentGraphicsPipeline->fragmentSamplerDescriptorSet;
|
2020-12-23 21:11:09 +00:00
|
|
|
descriptorSets[2] = renderer->currentGraphicsPipeline->vertexUBODescriptorSet;
|
|
|
|
descriptorSets[3] = renderer->currentGraphicsPipeline->fragmentUBODescriptorSet;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
2020-12-21 21:02:07 +00:00
|
|
|
dynamicOffsets[0] = renderer->vertexUBOOffset;
|
|
|
|
dynamicOffsets[1] = renderer->fragmentUBOOffset;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdBindDescriptorSets(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
2020-12-23 06:56:26 +00:00
|
|
|
renderer->currentGraphicsPipeline->layout,
|
2020-12-20 09:29:15 +00:00
|
|
|
0,
|
|
|
|
4,
|
|
|
|
descriptorSets,
|
|
|
|
2,
|
|
|
|
dynamicOffsets
|
|
|
|
));
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdDrawIndexed(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-23 06:56:26 +00:00
|
|
|
PrimitiveVerts(
|
|
|
|
renderer->currentGraphicsPipeline->primitiveType,
|
|
|
|
primitiveCount
|
|
|
|
),
|
2020-12-20 09:29:15 +00:00
|
|
|
instanceCount,
|
|
|
|
startIndex,
|
|
|
|
baseVertex,
|
|
|
|
0
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
static void VULKAN_DrawIndexedPrimitives(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t baseVertex,
|
|
|
|
uint32_t minVertexIndex,
|
|
|
|
uint32_t numVertices,
|
|
|
|
uint32_t startIndex,
|
|
|
|
uint32_t primitiveCount,
|
|
|
|
REFRESH_Buffer *indices,
|
|
|
|
REFRESH_IndexElementSize indexElementSize
|
|
|
|
) {
|
2020-12-20 09:29:15 +00:00
|
|
|
VULKAN_DrawInstancedPrimitives(
|
|
|
|
driverData,
|
|
|
|
baseVertex,
|
|
|
|
minVertexIndex,
|
|
|
|
numVertices,
|
|
|
|
startIndex,
|
|
|
|
primitiveCount,
|
|
|
|
1,
|
|
|
|
indices,
|
|
|
|
indexElementSize
|
|
|
|
);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_DrawPrimitives(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t vertexStart,
|
|
|
|
uint32_t primitiveCount
|
|
|
|
) {
|
2020-12-20 09:29:15 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VkDescriptorSet descriptorSets[4];
|
|
|
|
uint32_t dynamicOffsets[2];
|
|
|
|
|
2020-12-23 06:56:26 +00:00
|
|
|
descriptorSets[0] = renderer->currentGraphicsPipeline->vertexSamplerDescriptorSet;
|
|
|
|
descriptorSets[1] = renderer->currentGraphicsPipeline->fragmentSamplerDescriptorSet;
|
2020-12-23 21:11:09 +00:00
|
|
|
descriptorSets[2] = renderer->currentGraphicsPipeline->vertexUBODescriptorSet;
|
|
|
|
descriptorSets[3] = renderer->currentGraphicsPipeline->fragmentUBODescriptorSet;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
2020-12-21 21:02:07 +00:00
|
|
|
dynamicOffsets[0] = renderer->vertexUBOOffset;
|
|
|
|
dynamicOffsets[1] = renderer->fragmentUBOOffset;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdBindDescriptorSets(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
2020-12-23 06:56:26 +00:00
|
|
|
renderer->currentGraphicsPipeline->layout,
|
2020-12-20 09:29:15 +00:00
|
|
|
0,
|
|
|
|
4,
|
|
|
|
descriptorSets,
|
|
|
|
2,
|
|
|
|
dynamicOffsets
|
|
|
|
));
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdDraw(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
PrimitiveVerts(
|
2020-12-23 06:56:26 +00:00
|
|
|
renderer->currentGraphicsPipeline->primitiveType,
|
2020-12-20 09:29:15 +00:00
|
|
|
primitiveCount
|
|
|
|
),
|
|
|
|
1,
|
|
|
|
vertexStart,
|
|
|
|
0
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_RenderPass* VULKAN_CreateRenderPass(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_RenderPassCreateInfo *renderPassCreateInfo
|
|
|
|
) {
|
2020-12-17 08:19:02 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
|
|
|
|
VkResult vulkanResult;
|
2020-12-23 07:17:09 +00:00
|
|
|
VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1];
|
|
|
|
VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
|
|
|
|
VkAttachmentReference resolveReferences[MAX_COLOR_TARGET_BINDINGS + 1];
|
2020-12-17 08:19:02 +00:00
|
|
|
VkAttachmentReference depthStencilAttachmentReference;
|
|
|
|
VkRenderPassCreateInfo vkRenderPassCreateInfo;
|
|
|
|
VkSubpassDescription subpass;
|
|
|
|
VkRenderPass renderPass;
|
|
|
|
uint32_t i;
|
2020-12-22 02:34:57 +00:00
|
|
|
uint8_t multisampling = 0;
|
2020-12-17 08:19:02 +00:00
|
|
|
|
|
|
|
uint32_t attachmentDescriptionCount = 0;
|
|
|
|
uint32_t colorAttachmentReferenceCount = 0;
|
|
|
|
uint32_t resolveReferenceCount = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < renderPassCreateInfo->colorTargetCount; i += 1)
|
|
|
|
{
|
|
|
|
if (renderPassCreateInfo->colorTargetDescriptions[attachmentDescriptionCount].multisampleCount > REFRESH_SAMPLECOUNT_1)
|
|
|
|
{
|
2020-12-22 02:34:57 +00:00
|
|
|
multisampling = 1;
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
/* Resolve attachment and multisample attachment */
|
|
|
|
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].flags = 0;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].format
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].samples =
|
|
|
|
VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].loadOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].storeOp = RefreshToVK_StoreOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].storeOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
|
|
|
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
|
|
|
|
VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].initialLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].finalLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
resolveReferences[resolveReferenceCount].attachment =
|
|
|
|
attachmentDescriptionCount;
|
|
|
|
resolveReferences[resolveReferenceCount].layout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
attachmentDescriptionCount += 1;
|
|
|
|
resolveReferenceCount += 1;
|
|
|
|
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].flags = 0;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].format
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].multisampleCount
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].loadOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].storeOp = RefreshToVK_StoreOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].storeOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
|
|
|
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
|
|
|
|
VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].initialLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].finalLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
colorAttachmentReferences[colorAttachmentReferenceCount].attachment =
|
|
|
|
attachmentDescriptionCount;
|
|
|
|
colorAttachmentReferences[colorAttachmentReferenceCount].layout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
attachmentDescriptionCount += 1;
|
|
|
|
colorAttachmentReferenceCount += 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].flags = 0;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].format
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].samples =
|
|
|
|
VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].loadOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].storeOp = RefreshToVK_StoreOp[
|
|
|
|
renderPassCreateInfo->colorTargetDescriptions[i].storeOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
|
|
|
|
VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
|
|
|
|
VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].initialLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].finalLayout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
attachmentDescriptionCount += 1;
|
|
|
|
|
|
|
|
colorAttachmentReferences[colorAttachmentReferenceCount].attachment = i;
|
|
|
|
colorAttachmentReferences[colorAttachmentReferenceCount].layout =
|
|
|
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
colorAttachmentReferenceCount += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
|
|
subpass.flags = 0;
|
|
|
|
subpass.inputAttachmentCount = 0;
|
|
|
|
subpass.pInputAttachments = NULL;
|
|
|
|
subpass.colorAttachmentCount = renderPassCreateInfo->colorTargetCount;
|
|
|
|
subpass.pColorAttachments = colorAttachmentReferences;
|
|
|
|
subpass.preserveAttachmentCount = 0;
|
|
|
|
subpass.pPreserveAttachments = NULL;
|
|
|
|
|
|
|
|
if (renderPassCreateInfo->depthTargetDescription == NULL)
|
|
|
|
{
|
|
|
|
subpass.pDepthStencilAttachment = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].flags = 0;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_DepthFormat[
|
|
|
|
renderPassCreateInfo->depthTargetDescription->depthFormat
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].samples =
|
|
|
|
VK_SAMPLE_COUNT_1_BIT; /* FIXME: do these take multisamples? */
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[
|
|
|
|
renderPassCreateInfo->depthTargetDescription->loadOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].storeOp = RefreshToVK_StoreOp[
|
|
|
|
renderPassCreateInfo->depthTargetDescription->storeOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = RefreshToVK_LoadOp[
|
|
|
|
renderPassCreateInfo->depthTargetDescription->stencilLoadOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = RefreshToVK_StoreOp[
|
|
|
|
renderPassCreateInfo->depthTargetDescription->stencilStoreOp
|
|
|
|
];
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].initialLayout =
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
|
attachmentDescriptions[attachmentDescriptionCount].finalLayout =
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
depthStencilAttachmentReference.attachment =
|
|
|
|
attachmentDescriptionCount;
|
|
|
|
depthStencilAttachmentReference.layout =
|
|
|
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
|
|
|
|
|
|
subpass.pDepthStencilAttachment =
|
|
|
|
&depthStencilAttachmentReference;
|
|
|
|
|
|
|
|
attachmentDescriptionCount += 1;
|
|
|
|
}
|
|
|
|
|
2020-12-22 02:34:57 +00:00
|
|
|
if (multisampling)
|
|
|
|
{
|
|
|
|
subpass.pResolveAttachments = resolveReferences;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
subpass.pResolveAttachments = NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-17 08:19:02 +00:00
|
|
|
vkRenderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
|
|
vkRenderPassCreateInfo.pNext = NULL;
|
|
|
|
vkRenderPassCreateInfo.flags = 0;
|
|
|
|
vkRenderPassCreateInfo.pAttachments = attachmentDescriptions;
|
|
|
|
vkRenderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
|
|
|
|
vkRenderPassCreateInfo.subpassCount = 1;
|
|
|
|
vkRenderPassCreateInfo.pSubpasses = &subpass;
|
|
|
|
vkRenderPassCreateInfo.dependencyCount = 0;
|
|
|
|
vkRenderPassCreateInfo.pDependencies = NULL;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateRenderPass(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&vkRenderPassCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderPass
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateRenderPass", vulkanResult);
|
|
|
|
return NULL_RENDER_PASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (REFRESH_RenderPass*) renderPass;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
static uint8_t VULKAN_INTERNAL_CreateSamplerDescriptorPool(
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanRenderer *renderer,
|
|
|
|
REFRESH_PipelineLayoutCreateInfo *pipelineLayoutCreateInfo,
|
|
|
|
VkDescriptorPool *pDescriptorPool
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
|
|
|
|
VkDescriptorPoolSize poolSizes[2];
|
|
|
|
VkDescriptorPoolCreateInfo descriptorPoolInfo;
|
|
|
|
|
|
|
|
poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
poolSizes[0].descriptorCount = SAMPLER_POOL_SIZE;
|
|
|
|
|
|
|
|
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
poolSizes[1].descriptorCount = SAMPLER_POOL_SIZE;
|
|
|
|
|
|
|
|
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
|
|
descriptorPoolInfo.pNext = NULL;
|
|
|
|
descriptorPoolInfo.flags = 0;
|
|
|
|
descriptorPoolInfo.maxSets = 2 * SAMPLER_POOL_SIZE;
|
|
|
|
descriptorPoolInfo.poolSizeCount = 2;
|
|
|
|
descriptorPoolInfo.pPoolSizes = poolSizes;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDescriptorPool(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&descriptorPoolInfo,
|
|
|
|
NULL,
|
|
|
|
pDescriptorPool
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateDescriptorPool", vulkanResult);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
static REFRESH_GraphicsPipeline* VULKAN_CreateGraphicsPipeline(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_GraphicsPipelineCreateInfo *pipelineCreateInfo
|
|
|
|
) {
|
2020-12-17 19:40:49 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
uint32_t i;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) SDL_malloc(sizeof(VulkanGraphicsPipeline));
|
2020-12-17 19:40:49 +00:00
|
|
|
VkGraphicsPipelineCreateInfo vkPipelineCreateInfo;
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2];
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo;
|
2020-12-18 00:39:25 +00:00
|
|
|
VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, pipelineCreateInfo->vertexInputState.vertexBindingCount);
|
|
|
|
VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, pipelineCreateInfo->vertexInputState.vertexAttributeCount);
|
2020-12-17 19:40:49 +00:00
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
|
2020-12-18 00:39:25 +00:00
|
|
|
VkViewport *viewports = SDL_stack_alloc(VkViewport, pipelineCreateInfo->viewportState.viewportCount);
|
|
|
|
VkRect2D *scissors = SDL_stack_alloc(VkRect2D, pipelineCreateInfo->viewportState.scissorCount);
|
2020-12-17 19:40:49 +00:00
|
|
|
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
|
|
|
|
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo;
|
|
|
|
|
|
|
|
VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo;
|
|
|
|
VkStencilOpState frontStencilState;
|
|
|
|
VkStencilOpState backStencilState;
|
|
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo;
|
2020-12-18 00:39:25 +00:00
|
|
|
VkPipelineColorBlendAttachmentState *colorBlendAttachmentStates = SDL_stack_alloc(
|
|
|
|
VkPipelineColorBlendAttachmentState,
|
2020-12-17 19:40:49 +00:00
|
|
|
pipelineCreateInfo->colorBlendState.blendStateCount
|
2020-12-18 00:39:25 +00:00
|
|
|
);
|
2020-12-17 19:40:49 +00:00
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
|
|
|
|
VkPipelineLayout pipelineLayout;
|
|
|
|
VkDescriptorSetLayout setLayouts[4];
|
|
|
|
VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo;
|
|
|
|
|
2020-12-18 00:39:25 +00:00
|
|
|
VkDescriptorSetLayoutBinding *vertexSamplerLayoutBindings = SDL_stack_alloc(
|
|
|
|
VkDescriptorSetLayoutBinding,
|
2020-12-17 19:40:49 +00:00
|
|
|
pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindingCount
|
2020-12-18 00:39:25 +00:00
|
|
|
);
|
|
|
|
VkDescriptorSetLayoutBinding *fragmentSamplerLayoutBindings = SDL_stack_alloc(
|
|
|
|
VkDescriptorSetLayoutBinding,
|
2020-12-17 19:40:49 +00:00
|
|
|
pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindingCount
|
2020-12-18 00:39:25 +00:00
|
|
|
);
|
2020-12-17 19:40:49 +00:00
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
VkDescriptorSetAllocateInfo vertexUBODescriptorAllocateInfo;
|
|
|
|
VkDescriptorSetAllocateInfo fragmentUBODescriptorAllocateInfo;
|
|
|
|
|
|
|
|
VkWriteDescriptorSet uboWriteDescriptorSets[2];
|
|
|
|
VkDescriptorBufferInfo vertexUniformBufferInfo;
|
|
|
|
VkDescriptorBufferInfo fragmentUniformBufferInfo;
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
|
|
|
|
/* Shader stages */
|
|
|
|
|
|
|
|
shaderStageCreateInfos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
shaderStageCreateInfos[0].pNext = NULL;
|
|
|
|
shaderStageCreateInfos[0].flags = 0;
|
|
|
|
shaderStageCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
shaderStageCreateInfos[0].module = (VkShaderModule) pipelineCreateInfo->vertexShaderState.shaderModule;
|
|
|
|
shaderStageCreateInfos[0].pName = pipelineCreateInfo->vertexShaderState.entryPointName;
|
|
|
|
shaderStageCreateInfos[0].pSpecializationInfo = NULL;
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
graphicsPipeline->vertexUBOBlockSize =
|
|
|
|
VULKAN_INTERNAL_NextHighestAlignment(
|
|
|
|
pipelineCreateInfo->vertexShaderState.uniformBufferSize,
|
|
|
|
renderer->minUBOAlignment
|
|
|
|
);
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
shaderStageCreateInfos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
shaderStageCreateInfos[1].pNext = NULL;
|
|
|
|
shaderStageCreateInfos[1].flags = 0;
|
|
|
|
shaderStageCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
shaderStageCreateInfos[1].module = (VkShaderModule) pipelineCreateInfo->fragmentShaderState.shaderModule;
|
|
|
|
shaderStageCreateInfos[1].pName = pipelineCreateInfo->fragmentShaderState.entryPointName;
|
|
|
|
shaderStageCreateInfos[1].pSpecializationInfo = NULL;
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
graphicsPipeline->fragmentUBOBlockSize =
|
|
|
|
VULKAN_INTERNAL_NextHighestAlignment(
|
|
|
|
pipelineCreateInfo->fragmentShaderState.uniformBufferSize,
|
|
|
|
renderer->minUBOAlignment
|
|
|
|
);
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
/* Vertex input */
|
|
|
|
|
|
|
|
for (i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1)
|
|
|
|
{
|
|
|
|
vertexInputBindingDescriptions[i].binding = pipelineCreateInfo->vertexInputState.vertexBindings[i].binding;
|
|
|
|
vertexInputBindingDescriptions[i].inputRate = RefreshToVK_VertexInputRate[
|
|
|
|
pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate
|
|
|
|
];
|
|
|
|
vertexInputBindingDescriptions[i].stride = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < pipelineCreateInfo->vertexInputState.vertexAttributeCount; i += 1)
|
|
|
|
{
|
|
|
|
vertexInputAttributeDescriptions[i].binding = pipelineCreateInfo->vertexInputState.vertexAttributes[i].binding;
|
|
|
|
vertexInputAttributeDescriptions[i].format = RefreshToVK_VertexFormat[
|
|
|
|
pipelineCreateInfo->vertexInputState.vertexAttributes[i].format
|
|
|
|
];
|
|
|
|
vertexInputAttributeDescriptions[i].location = pipelineCreateInfo->vertexInputState.vertexAttributes[i].location;
|
|
|
|
vertexInputAttributeDescriptions[i].offset = pipelineCreateInfo->vertexInputState.vertexAttributes[i].offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
|
|
vertexInputStateCreateInfo.pNext = NULL;
|
|
|
|
vertexInputStateCreateInfo.flags = 0;
|
|
|
|
vertexInputStateCreateInfo.vertexBindingDescriptionCount = pipelineCreateInfo->vertexInputState.vertexBindingCount;
|
|
|
|
vertexInputStateCreateInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions;
|
|
|
|
vertexInputStateCreateInfo.vertexAttributeDescriptionCount = pipelineCreateInfo->vertexInputState.vertexAttributeCount;
|
|
|
|
vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
|
|
|
|
|
|
|
|
/* Topology */
|
|
|
|
|
|
|
|
inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
|
|
inputAssemblyStateCreateInfo.pNext = NULL;
|
|
|
|
inputAssemblyStateCreateInfo.flags = 0;
|
|
|
|
inputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
|
|
|
|
inputAssemblyStateCreateInfo.topology = RefreshToVK_PrimitiveType[
|
|
|
|
pipelineCreateInfo->topologyState.topology
|
|
|
|
];
|
|
|
|
|
|
|
|
/* Viewport */
|
|
|
|
|
|
|
|
for (i = 0; i < pipelineCreateInfo->viewportState.viewportCount; i += 1)
|
|
|
|
{
|
|
|
|
viewports[i].x = pipelineCreateInfo->viewportState.viewports[i].x;
|
|
|
|
viewports[i].y = pipelineCreateInfo->viewportState.viewports[i].y;
|
|
|
|
viewports[i].width = pipelineCreateInfo->viewportState.viewports[i].w;
|
|
|
|
viewports[i].height = pipelineCreateInfo->viewportState.viewports[i].h;
|
|
|
|
viewports[i].minDepth = pipelineCreateInfo->viewportState.viewports[i].minDepth;
|
|
|
|
viewports[i].maxDepth = pipelineCreateInfo->viewportState.viewports[i].maxDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < pipelineCreateInfo->viewportState.scissorCount; i += 1)
|
|
|
|
{
|
|
|
|
scissors[i].offset.x = pipelineCreateInfo->viewportState.scissors[i].x;
|
|
|
|
scissors[i].offset.y = pipelineCreateInfo->viewportState.scissors[i].y;
|
|
|
|
scissors[i].extent.width = pipelineCreateInfo->viewportState.scissors[i].w;
|
|
|
|
scissors[i].extent.height = pipelineCreateInfo->viewportState.scissors[i].h;
|
|
|
|
}
|
|
|
|
|
|
|
|
viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
|
|
viewportStateCreateInfo.pNext = NULL;
|
|
|
|
viewportStateCreateInfo.flags = 0;
|
|
|
|
viewportStateCreateInfo.viewportCount = pipelineCreateInfo->viewportState.viewportCount;
|
|
|
|
viewportStateCreateInfo.pViewports = viewports;
|
|
|
|
viewportStateCreateInfo.scissorCount = pipelineCreateInfo->viewportState.scissorCount;
|
|
|
|
viewportStateCreateInfo.pScissors = scissors;
|
|
|
|
|
|
|
|
/* Rasterization */
|
|
|
|
|
|
|
|
rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
|
|
rasterizationStateCreateInfo.pNext = NULL;
|
|
|
|
rasterizationStateCreateInfo.flags = 0;
|
|
|
|
rasterizationStateCreateInfo.depthClampEnable = pipelineCreateInfo->rasterizerState.depthClampEnable;
|
|
|
|
rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
|
|
|
|
rasterizationStateCreateInfo.polygonMode = RefreshToVK_PolygonMode[
|
|
|
|
pipelineCreateInfo->rasterizerState.fillMode
|
|
|
|
];
|
|
|
|
rasterizationStateCreateInfo.cullMode = RefreshToVK_CullMode[
|
|
|
|
pipelineCreateInfo->rasterizerState.cullMode
|
|
|
|
];
|
|
|
|
rasterizationStateCreateInfo.frontFace = RefreshToVK_FrontFace[
|
|
|
|
pipelineCreateInfo->rasterizerState.frontFace
|
|
|
|
];
|
|
|
|
rasterizationStateCreateInfo.depthBiasEnable =
|
|
|
|
pipelineCreateInfo->rasterizerState.depthBiasEnable;
|
|
|
|
rasterizationStateCreateInfo.depthBiasConstantFactor =
|
|
|
|
pipelineCreateInfo->rasterizerState.depthBiasConstantFactor;
|
|
|
|
rasterizationStateCreateInfo.depthBiasClamp =
|
|
|
|
pipelineCreateInfo->rasterizerState.depthBiasClamp;
|
|
|
|
rasterizationStateCreateInfo.depthBiasSlopeFactor =
|
|
|
|
pipelineCreateInfo->rasterizerState.depthBiasSlopeFactor;
|
|
|
|
rasterizationStateCreateInfo.lineWidth =
|
|
|
|
pipelineCreateInfo->rasterizerState.lineWidth;
|
|
|
|
|
|
|
|
/* Multisample */
|
|
|
|
|
|
|
|
multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
|
|
multisampleStateCreateInfo.pNext = NULL;
|
|
|
|
multisampleStateCreateInfo.flags = 0;
|
|
|
|
multisampleStateCreateInfo.rasterizationSamples = RefreshToVK_SampleCount[
|
|
|
|
pipelineCreateInfo->multisampleState.multisampleCount
|
|
|
|
];
|
|
|
|
multisampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
|
|
|
|
multisampleStateCreateInfo.minSampleShading = 1.0f;
|
|
|
|
multisampleStateCreateInfo.pSampleMask =
|
|
|
|
pipelineCreateInfo->multisampleState.sampleMask;
|
|
|
|
multisampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE;
|
|
|
|
multisampleStateCreateInfo.alphaToOneEnable = VK_FALSE;
|
|
|
|
|
|
|
|
/* Depth Stencil State */
|
|
|
|
|
|
|
|
frontStencilState.failOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.failOp
|
|
|
|
];
|
|
|
|
frontStencilState.passOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.passOp
|
|
|
|
];
|
|
|
|
frontStencilState.depthFailOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.depthFailOp
|
|
|
|
];
|
|
|
|
frontStencilState.compareOp = RefreshToVK_CompareOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.compareOp
|
|
|
|
];
|
|
|
|
frontStencilState.compareMask =
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.compareMask;
|
|
|
|
frontStencilState.writeMask =
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.writeMask;
|
|
|
|
frontStencilState.reference =
|
|
|
|
pipelineCreateInfo->depthStencilState.frontStencilState.reference;
|
|
|
|
|
|
|
|
backStencilState.failOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.failOp
|
|
|
|
];
|
|
|
|
backStencilState.passOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.passOp
|
|
|
|
];
|
|
|
|
backStencilState.depthFailOp = RefreshToVK_StencilOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.depthFailOp
|
|
|
|
];
|
|
|
|
backStencilState.compareOp = RefreshToVK_CompareOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.compareOp
|
|
|
|
];
|
|
|
|
backStencilState.compareMask =
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.compareMask;
|
|
|
|
backStencilState.writeMask =
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.writeMask;
|
|
|
|
backStencilState.reference =
|
|
|
|
pipelineCreateInfo->depthStencilState.backStencilState.reference;
|
|
|
|
|
|
|
|
|
|
|
|
depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
|
|
|
depthStencilStateCreateInfo.pNext = NULL;
|
|
|
|
depthStencilStateCreateInfo.flags = 0;
|
|
|
|
depthStencilStateCreateInfo.depthTestEnable =
|
|
|
|
pipelineCreateInfo->depthStencilState.depthTestEnable;
|
|
|
|
depthStencilStateCreateInfo.depthWriteEnable =
|
|
|
|
pipelineCreateInfo->depthStencilState.depthWriteEnable;
|
|
|
|
depthStencilStateCreateInfo.depthCompareOp = RefreshToVK_CompareOp[
|
|
|
|
pipelineCreateInfo->depthStencilState.compareOp
|
|
|
|
];
|
|
|
|
depthStencilStateCreateInfo.depthBoundsTestEnable =
|
|
|
|
pipelineCreateInfo->depthStencilState.depthBoundsTestEnable;
|
|
|
|
depthStencilStateCreateInfo.stencilTestEnable =
|
|
|
|
pipelineCreateInfo->depthStencilState.stencilTestEnable;
|
|
|
|
depthStencilStateCreateInfo.front = frontStencilState;
|
|
|
|
depthStencilStateCreateInfo.back = backStencilState;
|
|
|
|
depthStencilStateCreateInfo.minDepthBounds =
|
|
|
|
pipelineCreateInfo->depthStencilState.minDepthBounds;
|
|
|
|
depthStencilStateCreateInfo.maxDepthBounds =
|
|
|
|
pipelineCreateInfo->depthStencilState.maxDepthBounds;
|
|
|
|
|
|
|
|
/* Color Blend */
|
|
|
|
|
|
|
|
for (i = 0; i < pipelineCreateInfo->colorBlendState.blendStateCount; i += 1)
|
|
|
|
{
|
|
|
|
colorBlendAttachmentStates[i].blendEnable =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].blendEnable;
|
|
|
|
colorBlendAttachmentStates[i].srcColorBlendFactor = RefreshToVK_BlendFactor[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].srcColorBlendFactor
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].dstColorBlendFactor = RefreshToVK_BlendFactor[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].dstColorBlendFactor
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].colorBlendOp = RefreshToVK_BlendOp[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].colorBlendOp
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].srcAlphaBlendFactor = RefreshToVK_BlendFactor[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].srcAlphaBlendFactor
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].dstAlphaBlendFactor = RefreshToVK_BlendFactor[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].dstAlphaBlendFactor
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].alphaBlendOp = RefreshToVK_BlendOp[
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].alphaBlendOp
|
|
|
|
];
|
|
|
|
colorBlendAttachmentStates[i].colorWriteMask =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStates[i].colorWriteMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
colorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
|
|
|
colorBlendStateCreateInfo.pNext = NULL;
|
|
|
|
colorBlendStateCreateInfo.flags = 0;
|
|
|
|
colorBlendStateCreateInfo.logicOpEnable =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendOpEnable;
|
|
|
|
colorBlendStateCreateInfo.logicOp = RefreshToVK_LogicOp[
|
|
|
|
pipelineCreateInfo->colorBlendState.logicOp
|
|
|
|
];
|
|
|
|
colorBlendStateCreateInfo.attachmentCount =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendStateCount;
|
|
|
|
colorBlendStateCreateInfo.pAttachments =
|
|
|
|
colorBlendAttachmentStates;
|
|
|
|
colorBlendStateCreateInfo.blendConstants[0] =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendConstants[0];
|
|
|
|
colorBlendStateCreateInfo.blendConstants[1] =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendConstants[1];
|
|
|
|
colorBlendStateCreateInfo.blendConstants[2] =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendConstants[2];
|
|
|
|
colorBlendStateCreateInfo.blendConstants[3] =
|
|
|
|
pipelineCreateInfo->colorBlendState.blendConstants[3];
|
|
|
|
|
|
|
|
/* Pipeline Layout */
|
|
|
|
/* TODO: should we hash these? */
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
setLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
|
|
setLayoutCreateInfo.pNext = NULL;
|
|
|
|
setLayoutCreateInfo.flags = 0;
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
/* Vertex sampler layout */
|
2020-12-23 04:50:32 +00:00
|
|
|
if (pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindingCount == 0)
|
2020-12-17 19:40:49 +00:00
|
|
|
{
|
2020-12-23 04:50:32 +00:00
|
|
|
setLayouts[0] = renderer->emptyVertexSamplerLayout;
|
2020-12-17 19:40:49 +00:00
|
|
|
}
|
2020-12-23 04:50:32 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindingCount; i += 1)
|
|
|
|
{
|
|
|
|
vertexSamplerLayoutBindings[i].binding =
|
|
|
|
pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindings[i];
|
|
|
|
vertexSamplerLayoutBindings[i].descriptorCount = 1;
|
|
|
|
vertexSamplerLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
vertexSamplerLayoutBindings[i].stageFlags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
|
|
|
vertexSamplerLayoutBindings[i].pImmutableSamplers = NULL;
|
|
|
|
}
|
2020-12-17 19:40:49 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
setLayoutCreateInfo.bindingCount = pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindingCount;
|
|
|
|
setLayoutCreateInfo.pBindings = vertexSamplerLayoutBindings;
|
2020-12-17 19:40:49 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&setLayouts[0]
|
|
|
|
);
|
2020-12-18 00:39:25 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateDescriptorSetLayout", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create vertex sampler layout!");
|
|
|
|
|
|
|
|
SDL_stack_free(vertexInputBindingDescriptions);
|
|
|
|
SDL_stack_free(vertexInputAttributeDescriptions);
|
|
|
|
SDL_stack_free(viewports);
|
|
|
|
SDL_stack_free(scissors);
|
|
|
|
SDL_stack_free(colorBlendAttachmentStates);
|
|
|
|
SDL_stack_free(vertexSamplerLayoutBindings);
|
|
|
|
SDL_stack_free(fragmentSamplerLayoutBindings);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-12-17 19:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Frag sampler layout */
|
2020-12-23 04:50:32 +00:00
|
|
|
if (pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindingCount == 0)
|
2020-12-17 19:40:49 +00:00
|
|
|
{
|
2020-12-23 04:50:32 +00:00
|
|
|
setLayouts[1] = renderer->emptyFragmentSamplerLayout;
|
2020-12-17 19:40:49 +00:00
|
|
|
}
|
2020-12-23 04:50:32 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindingCount; i += 1)
|
|
|
|
{
|
|
|
|
fragmentSamplerLayoutBindings[i].binding =
|
|
|
|
pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindings[i];
|
|
|
|
fragmentSamplerLayoutBindings[i].descriptorCount = 1;
|
|
|
|
fragmentSamplerLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
fragmentSamplerLayoutBindings[i].stageFlags = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
|
|
fragmentSamplerLayoutBindings[i].pImmutableSamplers = NULL;
|
|
|
|
}
|
2020-12-17 19:40:49 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
setLayoutCreateInfo.bindingCount = pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindingCount;
|
|
|
|
setLayoutCreateInfo.pBindings = fragmentSamplerLayoutBindings;
|
2020-12-17 19:40:49 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&setLayouts[1]
|
|
|
|
);
|
2020-12-18 01:48:26 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateDescriptorSetLayout", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create fragment sampler layout!");
|
|
|
|
|
|
|
|
SDL_stack_free(vertexInputBindingDescriptions);
|
|
|
|
SDL_stack_free(vertexInputAttributeDescriptions);
|
|
|
|
SDL_stack_free(viewports);
|
|
|
|
SDL_stack_free(scissors);
|
|
|
|
SDL_stack_free(colorBlendAttachmentStates);
|
|
|
|
SDL_stack_free(vertexSamplerLayoutBindings);
|
|
|
|
SDL_stack_free(fragmentSamplerLayoutBindings);
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-12-17 19:40:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setLayouts[2] = renderer->vertexParamLayout;
|
|
|
|
setLayouts[3] = renderer->fragmentParamLayout;
|
|
|
|
|
|
|
|
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
|
|
pipelineLayoutCreateInfo.pNext = NULL;
|
|
|
|
pipelineLayoutCreateInfo.flags = 0;
|
2020-12-23 04:22:17 +00:00
|
|
|
pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
|
|
|
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
|
2020-12-17 19:40:49 +00:00
|
|
|
pipelineLayoutCreateInfo.setLayoutCount = 4;
|
|
|
|
pipelineLayoutCreateInfo.pSetLayouts = setLayouts;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreatePipelineLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&pipelineLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&pipelineLayout
|
|
|
|
);
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
graphicsPipeline->vertexSamplerLayout = setLayouts[0];
|
|
|
|
graphicsPipeline->fragmentSamplerLayout = setLayouts[1];
|
|
|
|
graphicsPipeline->vertexSamplerBindingCount = pipelineCreateInfo->pipelineLayoutCreateInfo.vertexSamplerBindingCount;
|
|
|
|
graphicsPipeline->fragmentSamplerBindingCount = pipelineCreateInfo->pipelineLayoutCreateInfo.fragmentSamplerBindingCount;
|
2020-12-20 09:29:15 +00:00
|
|
|
graphicsPipeline->layout = pipelineLayout;
|
2020-12-23 06:56:26 +00:00
|
|
|
graphicsPipeline->primitiveType = pipelineCreateInfo->topologyState.topology;
|
2020-12-19 05:35:21 +00:00
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
/* Pipeline */
|
|
|
|
|
|
|
|
vkPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
2020-12-23 04:22:17 +00:00
|
|
|
vkPipelineCreateInfo.pNext = NULL;
|
2020-12-17 19:40:49 +00:00
|
|
|
vkPipelineCreateInfo.flags = 0;
|
|
|
|
vkPipelineCreateInfo.stageCount = 2;
|
|
|
|
vkPipelineCreateInfo.pStages = shaderStageCreateInfos;
|
|
|
|
vkPipelineCreateInfo.pVertexInputState = &vertexInputStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pTessellationState = VK_NULL_HANDLE;
|
|
|
|
vkPipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pRasterizationState = &rasterizationStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
|
|
|
|
vkPipelineCreateInfo.pDynamicState = VK_NULL_HANDLE;
|
|
|
|
vkPipelineCreateInfo.layout = pipelineLayout;
|
|
|
|
vkPipelineCreateInfo.renderPass = (VkRenderPass) pipelineCreateInfo->renderPass;
|
|
|
|
vkPipelineCreateInfo.subpass = 0;
|
|
|
|
vkPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
|
|
|
vkPipelineCreateInfo.basePipelineIndex = 0;
|
|
|
|
|
|
|
|
/* TODO: enable pipeline caching */
|
|
|
|
vulkanResult = renderer->vkCreateGraphicsPipelines(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
1,
|
|
|
|
&vkPipelineCreateInfo,
|
|
|
|
NULL,
|
2020-12-19 04:08:07 +00:00
|
|
|
&graphicsPipeline->pipeline
|
2020-12-17 19:40:49 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
2020-12-18 01:48:26 +00:00
|
|
|
LogVulkanResult("vkCreateGraphicsPipelines", vulkanResult);
|
2020-12-17 19:40:49 +00:00
|
|
|
REFRESH_LogError("Failed to create graphics pipeline!");
|
2020-12-18 01:48:26 +00:00
|
|
|
|
2020-12-18 00:39:25 +00:00
|
|
|
SDL_stack_free(vertexInputBindingDescriptions);
|
|
|
|
SDL_stack_free(vertexInputAttributeDescriptions);
|
|
|
|
SDL_stack_free(viewports);
|
|
|
|
SDL_stack_free(scissors);
|
|
|
|
SDL_stack_free(colorBlendAttachmentStates);
|
|
|
|
SDL_stack_free(vertexSamplerLayoutBindings);
|
|
|
|
SDL_stack_free(fragmentSamplerLayoutBindings);
|
2020-12-17 19:40:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-18 00:39:25 +00:00
|
|
|
SDL_stack_free(vertexInputBindingDescriptions);
|
|
|
|
SDL_stack_free(vertexInputAttributeDescriptions);
|
|
|
|
SDL_stack_free(viewports);
|
|
|
|
SDL_stack_free(scissors);
|
|
|
|
SDL_stack_free(colorBlendAttachmentStates);
|
|
|
|
SDL_stack_free(vertexSamplerLayoutBindings);
|
|
|
|
SDL_stack_free(fragmentSamplerLayoutBindings);
|
2020-12-19 04:08:07 +00:00
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
/* Create sampler descriptor pool */
|
2020-12-20 09:29:15 +00:00
|
|
|
if (!VULKAN_INTERNAL_CreateSamplerDescriptorPool(
|
2020-12-19 04:17:50 +00:00
|
|
|
renderer,
|
|
|
|
&pipelineCreateInfo->pipelineLayoutCreateInfo,
|
|
|
|
&graphicsPipeline->descriptorPool
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create descriptor pool!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
renderer->descriptorPools = SDL_realloc(
|
|
|
|
renderer->descriptorPools,
|
|
|
|
renderer->descriptorPoolCount + 1
|
|
|
|
);
|
|
|
|
renderer->descriptorPools[renderer->descriptorPoolCount + 1] =
|
|
|
|
graphicsPipeline->descriptorPool;
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
/* Allocate uniform buffer descriptors */
|
|
|
|
|
|
|
|
vertexUBODescriptorAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
vertexUBODescriptorAllocateInfo.pNext = NULL;
|
|
|
|
vertexUBODescriptorAllocateInfo.descriptorPool = renderer->defaultDescriptorPool;
|
|
|
|
vertexUBODescriptorAllocateInfo.descriptorSetCount = 1;
|
|
|
|
vertexUBODescriptorAllocateInfo.pSetLayouts = &renderer->vertexParamLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&vertexUBODescriptorAllocateInfo,
|
|
|
|
&graphicsPipeline->vertexUBODescriptorSet
|
|
|
|
);
|
|
|
|
|
|
|
|
fragmentUBODescriptorAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
fragmentUBODescriptorAllocateInfo.pNext = NULL;
|
|
|
|
fragmentUBODescriptorAllocateInfo.descriptorPool = renderer->defaultDescriptorPool;
|
|
|
|
fragmentUBODescriptorAllocateInfo.descriptorSetCount = 1;
|
|
|
|
fragmentUBODescriptorAllocateInfo.pSetLayouts = &renderer->fragmentParamLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&fragmentUBODescriptorAllocateInfo,
|
|
|
|
&graphicsPipeline->fragmentUBODescriptorSet
|
|
|
|
);
|
|
|
|
|
|
|
|
vertexUniformBufferInfo.buffer = renderer->vertexUBO->subBuffers[0]->buffer;
|
|
|
|
vertexUniformBufferInfo.offset = 0;
|
|
|
|
vertexUniformBufferInfo.range = graphicsPipeline->vertexUBOBlockSize;
|
|
|
|
|
|
|
|
fragmentUniformBufferInfo.buffer = renderer->fragmentUBO->subBuffers[0]->buffer;
|
|
|
|
fragmentUniformBufferInfo.offset = 0;
|
|
|
|
fragmentUniformBufferInfo.range = graphicsPipeline->fragmentUBOBlockSize;
|
|
|
|
|
|
|
|
uboWriteDescriptorSets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
uboWriteDescriptorSets[0].pNext = NULL;
|
|
|
|
uboWriteDescriptorSets[0].descriptorCount = 1;
|
|
|
|
uboWriteDescriptorSets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
|
|
|
uboWriteDescriptorSets[0].dstArrayElement = 0;
|
|
|
|
uboWriteDescriptorSets[0].dstBinding = 0;
|
|
|
|
uboWriteDescriptorSets[0].dstSet = graphicsPipeline->vertexUBODescriptorSet;
|
|
|
|
uboWriteDescriptorSets[0].pBufferInfo = &vertexUniformBufferInfo;
|
|
|
|
uboWriteDescriptorSets[0].pImageInfo = NULL;
|
|
|
|
uboWriteDescriptorSets[0].pTexelBufferView = NULL;
|
|
|
|
|
|
|
|
uboWriteDescriptorSets[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
uboWriteDescriptorSets[1].pNext = NULL;
|
|
|
|
uboWriteDescriptorSets[1].descriptorCount = 1;
|
|
|
|
uboWriteDescriptorSets[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
|
|
|
uboWriteDescriptorSets[1].dstArrayElement = 0;
|
|
|
|
uboWriteDescriptorSets[1].dstBinding = 0;
|
|
|
|
uboWriteDescriptorSets[1].dstSet = graphicsPipeline->fragmentUBODescriptorSet;
|
|
|
|
uboWriteDescriptorSets[1].pBufferInfo = &fragmentUniformBufferInfo;
|
|
|
|
uboWriteDescriptorSets[1].pImageInfo = NULL;
|
|
|
|
uboWriteDescriptorSets[1].pTexelBufferView = NULL;
|
|
|
|
|
|
|
|
renderer->vkUpdateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
2,
|
|
|
|
uboWriteDescriptorSets,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
return (REFRESH_GraphicsPipeline*) graphicsPipeline;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_Sampler* VULKAN_CreateSampler(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_SamplerStateCreateInfo *samplerStateCreateInfo
|
|
|
|
) {
|
2020-12-18 01:48:26 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VkSampler sampler;
|
2020-12-18 20:58:03 +00:00
|
|
|
|
2020-12-18 01:48:26 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
|
|
|
|
|
|
|
|
VkSamplerCreateInfo vkSamplerCreateInfo;
|
|
|
|
vkSamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
|
|
vkSamplerCreateInfo.pNext = NULL;
|
|
|
|
vkSamplerCreateInfo.flags = 0;
|
|
|
|
vkSamplerCreateInfo.magFilter = RefreshToVK_SamplerFilter[
|
|
|
|
samplerStateCreateInfo->magFilter
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.minFilter = RefreshToVK_SamplerFilter[
|
|
|
|
samplerStateCreateInfo->minFilter
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.mipmapMode = RefreshToVK_SamplerMipmapMode[
|
|
|
|
samplerStateCreateInfo->mipmapMode
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.addressModeU = RefreshToVK_SamplerAddressMode[
|
|
|
|
samplerStateCreateInfo->addressModeU
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.addressModeV = RefreshToVK_SamplerAddressMode[
|
|
|
|
samplerStateCreateInfo->addressModeV
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.addressModeW = RefreshToVK_SamplerAddressMode[
|
|
|
|
samplerStateCreateInfo->addressModeW
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.mipLodBias = samplerStateCreateInfo->mipLodBias;
|
|
|
|
vkSamplerCreateInfo.anisotropyEnable = samplerStateCreateInfo->anisotropyEnable;
|
|
|
|
vkSamplerCreateInfo.maxAnisotropy = samplerStateCreateInfo->maxAnisotropy;
|
|
|
|
vkSamplerCreateInfo.compareEnable = samplerStateCreateInfo->compareEnable;
|
|
|
|
vkSamplerCreateInfo.compareOp = RefreshToVK_CompareOp[
|
|
|
|
samplerStateCreateInfo->compareOp
|
|
|
|
];
|
|
|
|
vkSamplerCreateInfo.minLod = samplerStateCreateInfo->minLod;
|
|
|
|
vkSamplerCreateInfo.maxLod = samplerStateCreateInfo->maxLod;
|
2020-12-18 20:58:03 +00:00
|
|
|
vkSamplerCreateInfo.borderColor = RefreshToVK_BorderColor[
|
|
|
|
samplerStateCreateInfo->borderColor
|
|
|
|
];
|
2020-12-18 01:48:26 +00:00
|
|
|
vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateSampler(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&vkSamplerCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&sampler
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateSampler", vulkanResult);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (REFRESH_Sampler*) sampler;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_Framebuffer* VULKAN_CreateFramebuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_FramebufferCreateInfo *framebufferCreateInfo
|
|
|
|
) {
|
2020-12-18 20:58:03 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VkFramebufferCreateInfo vkFramebufferCreateInfo;
|
|
|
|
|
|
|
|
VkImageView *imageViews;
|
|
|
|
uint32_t colorAttachmentCount = framebufferCreateInfo->colorTargetCount;
|
2020-12-19 00:42:54 +00:00
|
|
|
uint32_t attachmentCount = colorAttachmentCount;
|
2020-12-18 20:58:03 +00:00
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
2020-12-23 07:17:09 +00:00
|
|
|
VulkanFramebuffer *vulkanFramebuffer = (VulkanFramebuffer*) SDL_malloc(sizeof(VulkanFramebuffer));
|
2020-12-18 20:58:03 +00:00
|
|
|
|
2020-12-23 07:17:09 +00:00
|
|
|
if (framebufferCreateInfo->pDepthStencilTarget != NULL)
|
2020-12-19 00:42:54 +00:00
|
|
|
{
|
|
|
|
attachmentCount += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
imageViews = SDL_stack_alloc(VkImageView, attachmentCount);
|
2020-12-18 20:58:03 +00:00
|
|
|
|
|
|
|
for (i = 0; i < colorAttachmentCount; i += 1)
|
|
|
|
{
|
2020-12-19 00:39:03 +00:00
|
|
|
imageViews[i] = ((VulkanColorTarget*)framebufferCreateInfo->pColorTargets[i])->view;
|
2020-12-18 20:58:03 +00:00
|
|
|
}
|
|
|
|
|
2020-12-23 07:17:09 +00:00
|
|
|
if (framebufferCreateInfo->pDepthStencilTarget != NULL)
|
2020-12-19 00:42:54 +00:00
|
|
|
{
|
2020-12-23 07:17:09 +00:00
|
|
|
imageViews[colorAttachmentCount] = ((VulkanDepthStencilTarget*)framebufferCreateInfo->pDepthStencilTarget)->view;
|
2020-12-19 00:42:54 +00:00
|
|
|
}
|
|
|
|
|
2020-12-18 20:58:03 +00:00
|
|
|
vkFramebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
|
|
vkFramebufferCreateInfo.pNext = NULL;
|
|
|
|
vkFramebufferCreateInfo.flags = 0;
|
|
|
|
vkFramebufferCreateInfo.renderPass = (VkRenderPass) framebufferCreateInfo->renderPass;
|
2020-12-19 00:42:54 +00:00
|
|
|
vkFramebufferCreateInfo.attachmentCount = attachmentCount;
|
2020-12-18 20:58:03 +00:00
|
|
|
vkFramebufferCreateInfo.pAttachments = imageViews;
|
|
|
|
vkFramebufferCreateInfo.width = framebufferCreateInfo->width;
|
|
|
|
vkFramebufferCreateInfo.height = framebufferCreateInfo->height;
|
2020-12-19 00:39:03 +00:00
|
|
|
vkFramebufferCreateInfo.layers = 1;
|
2020-12-18 20:58:03 +00:00
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateFramebuffer(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&vkFramebufferCreateInfo,
|
|
|
|
NULL,
|
2020-12-23 07:17:09 +00:00
|
|
|
&vulkanFramebuffer->framebuffer
|
2020-12-18 20:58:03 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateFramebuffer", vulkanResult);
|
|
|
|
SDL_stack_free(imageViews);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-23 07:17:09 +00:00
|
|
|
for (i = 0; i < colorAttachmentCount; i += 1)
|
|
|
|
{
|
|
|
|
vulkanFramebuffer->colorTargets[i] =
|
|
|
|
(VulkanColorTarget*) framebufferCreateInfo->pColorTargets[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanFramebuffer->colorTargetCount = colorAttachmentCount;
|
|
|
|
vulkanFramebuffer->depthStencilTarget =
|
|
|
|
(VulkanDepthStencilTarget*) framebufferCreateInfo->pDepthStencilTarget;
|
|
|
|
|
2020-12-18 20:58:03 +00:00
|
|
|
SDL_stack_free(imageViews);
|
2020-12-23 07:17:09 +00:00
|
|
|
return (REFRESH_Framebuffer*) vulkanFramebuffer;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_ShaderModule* VULKAN_CreateShaderModule(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_ShaderModuleCreateInfo *shaderModuleCreateInfo
|
|
|
|
) {
|
2020-12-19 01:25:22 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VkShaderModule shaderModule;
|
|
|
|
VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
|
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
|
|
|
|
vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
|
|
vkShaderModuleCreateInfo.pNext = NULL;
|
|
|
|
vkShaderModuleCreateInfo.flags = 0;
|
|
|
|
vkShaderModuleCreateInfo.codeSize = shaderModuleCreateInfo->codeSize;
|
|
|
|
vkShaderModuleCreateInfo.pCode = (uint32_t*) shaderModuleCreateInfo->byteCode;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateShaderModule(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&vkShaderModuleCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&shaderModule
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateShaderModule", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create shader module!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (REFRESH_ShaderModule*) shaderModule;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
/* texture should be an alloc'd but uninitialized VulkanTexture */
|
|
|
|
static uint8_t VULKAN_INTERNAL_CreateTexture(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
uint32_t depth,
|
|
|
|
uint32_t isCube,
|
|
|
|
VkSampleCountFlagBits samples,
|
|
|
|
uint32_t levelCount,
|
|
|
|
VkFormat format,
|
|
|
|
VkImageAspectFlags aspectMask,
|
|
|
|
VkImageTiling tiling,
|
|
|
|
VkImageType imageType,
|
|
|
|
VkImageUsageFlags usage,
|
|
|
|
VulkanTexture *texture
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
VkImageCreateInfo imageCreateInfo;
|
2020-12-19 00:39:03 +00:00
|
|
|
VkImageCreateFlags imageCreateFlags = 0;
|
2020-12-18 22:35:33 +00:00
|
|
|
VkImageViewCreateInfo imageViewCreateInfo;
|
|
|
|
uint8_t findMemoryResult;
|
2020-12-19 00:39:03 +00:00
|
|
|
uint8_t is3D = depth > 1 ? 1 : 0;
|
2020-12-18 22:35:33 +00:00
|
|
|
uint8_t layerCount = isCube ? 6 : 1;
|
|
|
|
VkComponentMapping swizzle = IDENTITY_SWIZZLE;
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
if (isCube)
|
|
|
|
{
|
|
|
|
imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
|
|
|
}
|
|
|
|
else if (is3D)
|
|
|
|
{
|
|
|
|
imageCreateFlags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
|
|
|
}
|
|
|
|
|
2020-12-18 22:35:33 +00:00
|
|
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
|
|
imageCreateInfo.pNext = NULL;
|
2020-12-19 00:39:03 +00:00
|
|
|
imageCreateInfo.flags = imageCreateFlags;
|
2020-12-18 22:35:33 +00:00
|
|
|
imageCreateInfo.imageType = imageType;
|
|
|
|
imageCreateInfo.format = format;
|
|
|
|
imageCreateInfo.extent.width = width;
|
|
|
|
imageCreateInfo.extent.height = height;
|
|
|
|
imageCreateInfo.extent.depth = depth;
|
|
|
|
imageCreateInfo.mipLevels = levelCount;
|
|
|
|
imageCreateInfo.arrayLayers = layerCount;
|
|
|
|
imageCreateInfo.samples = samples;
|
|
|
|
imageCreateInfo.tiling = tiling;
|
|
|
|
imageCreateInfo.usage = usage;
|
|
|
|
// FIXME: would this interfere with pixel data sharing?
|
|
|
|
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
imageCreateInfo.queueFamilyIndexCount = 0;
|
|
|
|
imageCreateInfo.pQueueFamilyIndices = NULL;
|
|
|
|
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImage(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&texture->image
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateImage", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create texture!");
|
|
|
|
}
|
|
|
|
|
|
|
|
findMemoryResult = VULKAN_INTERNAL_FindAvailableMemory(
|
|
|
|
renderer,
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
texture->image,
|
|
|
|
&texture->allocation,
|
|
|
|
&texture->offset,
|
|
|
|
&texture->memorySize
|
|
|
|
);
|
|
|
|
|
|
|
|
/* No device memory available, time to die */
|
|
|
|
if (findMemoryResult == 0 || findMemoryResult == 2)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to find texture memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkBindImageMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
texture->image,
|
|
|
|
texture->allocation->memory,
|
|
|
|
texture->offset
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkBindImageMemory", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to bind texture memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
imageViewCreateInfo.pNext = NULL;
|
|
|
|
imageViewCreateInfo.flags = 0;
|
|
|
|
imageViewCreateInfo.image = texture->image;
|
|
|
|
imageViewCreateInfo.format = format;
|
|
|
|
imageViewCreateInfo.components = swizzle;
|
|
|
|
imageViewCreateInfo.subresourceRange.aspectMask = aspectMask;
|
|
|
|
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
|
|
|
imageViewCreateInfo.subresourceRange.levelCount = levelCount;
|
|
|
|
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
|
imageViewCreateInfo.subresourceRange.layerCount = layerCount;
|
|
|
|
|
|
|
|
if (isCube)
|
|
|
|
{
|
|
|
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
|
|
|
}
|
|
|
|
else if (imageType == VK_IMAGE_TYPE_2D)
|
|
|
|
{
|
|
|
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
}
|
|
|
|
else if (imageType == VK_IMAGE_TYPE_3D)
|
|
|
|
{
|
|
|
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REFRESH_LogError("invalid image type: %u", imageType);
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImageView(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageViewCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&texture->view
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateImageView", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create texture image view");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
texture->dimensions.width = width;
|
|
|
|
texture->dimensions.height = height;
|
|
|
|
texture->depth = depth;
|
2020-12-19 00:39:03 +00:00
|
|
|
texture->format = format;
|
2020-12-18 22:35:33 +00:00
|
|
|
texture->levelCount = levelCount;
|
|
|
|
texture->layerCount = layerCount;
|
|
|
|
texture->resourceAccessType = RESOURCE_ACCESS_NONE;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CreateTextureDepthStencil(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
VkFormat format,
|
|
|
|
VulkanDepthStencilTexture *texture
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
VkImageCreateInfo imageCreateInfo;
|
|
|
|
VkImageViewCreateInfo imageViewCreateInfo;
|
|
|
|
uint8_t findMemoryResult;
|
|
|
|
uint8_t layerCount = 1;
|
|
|
|
VkComponentMapping swizzle = IDENTITY_SWIZZLE;
|
|
|
|
uint32_t usageFlags = (
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
|
|
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
|
|
|
|
);
|
|
|
|
VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
|
|
|
|
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
|
|
imageCreateInfo.pNext = NULL;
|
|
|
|
imageCreateInfo.flags = 0;
|
|
|
|
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
|
|
imageCreateInfo.format = format;
|
|
|
|
imageCreateInfo.extent.width = width;
|
|
|
|
imageCreateInfo.extent.height = height;
|
|
|
|
imageCreateInfo.extent.depth = 1;
|
|
|
|
imageCreateInfo.mipLevels = 1;
|
|
|
|
imageCreateInfo.arrayLayers = layerCount;
|
|
|
|
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
imageCreateInfo.usage = usageFlags;
|
|
|
|
// FIXME: would this interfere with pixel data sharing?
|
|
|
|
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
imageCreateInfo.queueFamilyIndexCount = 0;
|
|
|
|
imageCreateInfo.pQueueFamilyIndices = NULL;
|
|
|
|
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImage(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&texture->image
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateImage", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create texture!");
|
|
|
|
}
|
|
|
|
|
|
|
|
findMemoryResult = VULKAN_INTERNAL_FindAvailableMemory(
|
|
|
|
renderer,
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
texture->image,
|
|
|
|
&texture->allocation,
|
|
|
|
&texture->offset,
|
|
|
|
&texture->memorySize
|
|
|
|
);
|
|
|
|
|
|
|
|
/* No device memory available, time to die */
|
|
|
|
if (findMemoryResult == 0 || findMemoryResult == 2)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to find texture memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkBindImageMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
texture->image,
|
|
|
|
texture->allocation->memory,
|
|
|
|
texture->offset
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkBindImageMemory", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to bind texture memory!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DepthFormatContainsStencil(format))
|
|
|
|
{
|
|
|
|
aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
imageViewCreateInfo.pNext = NULL;
|
|
|
|
imageViewCreateInfo.flags = 0;
|
|
|
|
imageViewCreateInfo.image = texture->image;
|
|
|
|
imageViewCreateInfo.format = format;
|
|
|
|
imageViewCreateInfo.components = swizzle;
|
|
|
|
imageViewCreateInfo.subresourceRange.aspectMask = aspectFlags;
|
|
|
|
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
|
|
|
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
|
|
|
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
|
|
|
imageViewCreateInfo.subresourceRange.layerCount = layerCount;
|
|
|
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImageView(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageViewCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&texture->view
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateImageView", vulkanResult);
|
|
|
|
REFRESH_LogError("Failed to create texture image view");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
texture->dimensions.width = width;
|
|
|
|
texture->dimensions.height = height;
|
2020-12-19 00:39:03 +00:00
|
|
|
texture->format = format;
|
2020-12-18 22:35:33 +00:00
|
|
|
texture->resourceAccessType = RESOURCE_ACCESS_NONE;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
static REFRESH_Texture* VULKAN_CreateTexture2D(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_SurfaceFormat format,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
2020-12-18 22:35:33 +00:00
|
|
|
uint32_t levelCount,
|
|
|
|
uint8_t canBeRenderTarget
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-18 22:35:33 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *result;
|
|
|
|
uint32_t usageFlags = (
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
|
|
|
);
|
|
|
|
|
|
|
|
if (canBeRenderTarget)
|
|
|
|
{
|
|
|
|
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture));
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_CreateTexture(
|
|
|
|
renderer,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
levelCount,
|
|
|
|
RefreshToVK_SurfaceFormat[format],
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
usageFlags,
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
return (REFRESH_Texture*) result;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_Texture* VULKAN_CreateTexture3D(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_SurfaceFormat format,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
uint32_t depth,
|
2020-12-18 22:35:33 +00:00
|
|
|
uint32_t levelCount,
|
|
|
|
uint8_t canBeRenderTarget
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-18 22:35:33 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *result;
|
|
|
|
uint32_t usageFlags = (
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
|
|
|
);
|
|
|
|
|
|
|
|
if (canBeRenderTarget)
|
|
|
|
{
|
|
|
|
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture));
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_CreateTexture(
|
|
|
|
renderer,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
depth,
|
|
|
|
0,
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
levelCount,
|
|
|
|
RefreshToVK_SurfaceFormat[format],
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_TYPE_3D,
|
|
|
|
usageFlags,
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
return (REFRESH_Texture*) result;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_Texture* VULKAN_CreateTextureCube(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_SurfaceFormat format,
|
|
|
|
uint32_t size,
|
2020-12-18 22:35:33 +00:00
|
|
|
uint32_t levelCount,
|
|
|
|
uint8_t canBeRenderTarget
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-18 22:35:33 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *result;
|
|
|
|
uint32_t usageFlags = (
|
|
|
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
|
|
|
);
|
|
|
|
|
|
|
|
if (canBeRenderTarget)
|
|
|
|
{
|
|
|
|
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture));
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_CreateTexture(
|
|
|
|
renderer,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
levelCount,
|
|
|
|
RefreshToVK_SurfaceFormat[format],
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
usageFlags,
|
|
|
|
result
|
|
|
|
);
|
|
|
|
|
|
|
|
return (REFRESH_Texture*) result;
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:12 +00:00
|
|
|
static REFRESH_ColorTarget* VULKAN_CreateColorTarget(
|
2020-12-18 22:35:33 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-19 00:39:03 +00:00
|
|
|
REFRESH_SampleCount multisampleCount,
|
2020-12-22 02:54:36 +00:00
|
|
|
REFRESH_TextureSlice *textureSlice
|
2020-12-18 22:35:33 +00:00
|
|
|
) {
|
2020-12-19 00:39:03 +00:00
|
|
|
VkResult vulkanResult;
|
2020-12-18 22:35:33 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
2020-12-19 00:39:03 +00:00
|
|
|
VulkanColorTarget *colorTarget = (VulkanColorTarget*) SDL_malloc(sizeof(VulkanColorTarget));
|
|
|
|
VkImageViewCreateInfo imageViewCreateInfo;
|
|
|
|
VkComponentMapping swizzle = IDENTITY_SWIZZLE;
|
2020-12-18 22:35:33 +00:00
|
|
|
|
2020-12-22 02:54:36 +00:00
|
|
|
colorTarget->texture = (VulkanTexture*) textureSlice->texture;
|
2020-12-23 07:17:09 +00:00
|
|
|
colorTarget->layer = textureSlice->layer;
|
2020-12-19 00:39:03 +00:00
|
|
|
colorTarget->multisampleTexture = NULL;
|
|
|
|
colorTarget->multisampleCount = 1;
|
2020-12-18 22:35:33 +00:00
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
/* create resolve target for multisample */
|
2020-12-22 01:59:08 +00:00
|
|
|
if (multisampleCount > REFRESH_SAMPLECOUNT_1)
|
2020-12-19 00:39:03 +00:00
|
|
|
{
|
|
|
|
colorTarget->multisampleTexture =
|
|
|
|
(VulkanTexture*) SDL_malloc(sizeof(VulkanTexture));
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_CreateTexture(
|
|
|
|
renderer,
|
|
|
|
colorTarget->texture->dimensions.width,
|
|
|
|
colorTarget->texture->dimensions.height,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
RefreshToVK_SampleCount[multisampleCount],
|
|
|
|
1,
|
|
|
|
RefreshToVK_SurfaceFormat[colorTarget->texture->format],
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
VK_IMAGE_TYPE_2D,
|
|
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
|
|
colorTarget->multisampleTexture
|
|
|
|
);
|
|
|
|
colorTarget->multisampleCount = multisampleCount;
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
colorTarget->multisampleTexture->layerCount,
|
|
|
|
0,
|
|
|
|
colorTarget->multisampleTexture->levelCount,
|
|
|
|
0,
|
|
|
|
colorTarget->multisampleTexture->image,
|
|
|
|
&colorTarget->multisampleTexture->resourceAccessType
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create framebuffer compatible views for RenderTarget */
|
|
|
|
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
imageViewCreateInfo.pNext = NULL;
|
|
|
|
imageViewCreateInfo.flags = 0;
|
|
|
|
imageViewCreateInfo.image = colorTarget->texture->image;
|
|
|
|
imageViewCreateInfo.format = colorTarget->texture->format;
|
|
|
|
imageViewCreateInfo.components = swizzle;
|
|
|
|
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
|
|
|
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
2020-12-22 02:54:36 +00:00
|
|
|
imageViewCreateInfo.subresourceRange.baseArrayLayer = textureSlice->layer;
|
2020-12-19 00:39:03 +00:00
|
|
|
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
|
|
|
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateImageView(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&imageViewCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&colorTarget->view
|
2020-12-18 22:35:33 +00:00
|
|
|
);
|
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult(
|
|
|
|
"vkCreateImageView",
|
|
|
|
vulkanResult
|
|
|
|
);
|
|
|
|
REFRESH_LogError("Failed to create color attachment image view");
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-12-17 01:23:49 +00:00
|
|
|
|
2020-12-19 00:39:03 +00:00
|
|
|
return (REFRESH_ColorTarget*) colorTarget;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:12 +00:00
|
|
|
static REFRESH_DepthStencilTarget* VULKAN_CreateDepthStencilTarget(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
2020-12-19 00:39:03 +00:00
|
|
|
REFRESH_DepthFormat format
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-19 00:39:03 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanDepthStencilTarget *depthStencilTarget =
|
|
|
|
(VulkanDepthStencilTarget*) SDL_malloc(
|
|
|
|
sizeof(VulkanDepthStencilTarget)
|
|
|
|
);
|
|
|
|
|
|
|
|
VulkanDepthStencilTexture *texture =
|
|
|
|
(VulkanDepthStencilTexture*) SDL_malloc(
|
|
|
|
sizeof(VulkanDepthStencilTexture)
|
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_CreateTextureDepthStencil(
|
|
|
|
renderer,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
RefreshToVK_DepthFormat[format],
|
|
|
|
texture
|
|
|
|
);
|
|
|
|
|
|
|
|
depthStencilTarget->texture = texture;
|
|
|
|
depthStencilTarget->view = texture->view;
|
|
|
|
|
|
|
|
return (REFRESH_DepthStencilTarget*) depthStencilTarget;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:12 +00:00
|
|
|
static REFRESH_Buffer* VULKAN_CreateVertexBuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t sizeInBytes
|
|
|
|
) {
|
2020-12-19 01:32:27 +00:00
|
|
|
VulkanBuffer *buffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if(!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
(VulkanRenderer*) driverData,
|
|
|
|
sizeInBytes,
|
|
|
|
RESOURCE_ACCESS_VERTEX_BUFFER,
|
|
|
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
2020-12-19 04:08:07 +00:00
|
|
|
SUB_BUFFER_COUNT,
|
2020-12-19 01:32:27 +00:00
|
|
|
buffer
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create vertex buffer!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (REFRESH_Buffer*) buffer;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:50:12 +00:00
|
|
|
static REFRESH_Buffer* VULKAN_CreateIndexBuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
uint32_t sizeInBytes
|
|
|
|
) {
|
2020-12-19 01:32:27 +00:00
|
|
|
VulkanBuffer *buffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
(VulkanRenderer*) driverData,
|
|
|
|
sizeInBytes,
|
|
|
|
RESOURCE_ACCESS_INDEX_BUFFER,
|
|
|
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
2020-12-19 04:08:07 +00:00
|
|
|
SUB_BUFFER_COUNT,
|
2020-12-19 01:32:27 +00:00
|
|
|
buffer
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create index buffer!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (REFRESH_Buffer*) buffer;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
/* Setters */
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_DestroyTextureStagingBuffer(
|
|
|
|
VulkanRenderer *renderer
|
|
|
|
) {
|
|
|
|
VULKAN_INTERNAL_DestroyBuffer(
|
|
|
|
renderer,
|
|
|
|
renderer->textureStagingBuffer
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_INTERNAL_MaybeExpandStagingBuffer(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkDeviceSize size
|
|
|
|
) {
|
|
|
|
if (size <= renderer->textureStagingBuffer->size)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_DestroyTextureStagingBuffer(renderer);
|
|
|
|
|
|
|
|
renderer->textureStagingBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
renderer,
|
|
|
|
size,
|
|
|
|
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
|
|
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
|
|
|
1,
|
|
|
|
renderer->textureStagingBuffer
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to expand texture staging buffer!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
static void VULKAN_SetTextureData2D(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t w,
|
|
|
|
uint32_t h,
|
|
|
|
uint32_t level,
|
|
|
|
void *data,
|
|
|
|
uint32_t dataLengthInBytes
|
|
|
|
) {
|
2020-12-19 01:03:26 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *vulkanTexture = (VulkanTexture*) texture;
|
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
|
uint8_t *mapPointer;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLengthInBytes);
|
|
|
|
|
2020-12-19 01:03:26 +00:00
|
|
|
vulkanResult = renderer->vkMapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->offset,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->size,
|
2020-12-19 01:03:26 +00:00
|
|
|
0,
|
|
|
|
(void**) &mapPointer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to map buffer memory!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(mapPointer, data, dataLengthInBytes);
|
|
|
|
|
|
|
|
renderer->vkUnmapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory
|
2020-12-19 01:03:26 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
vulkanTexture->layerCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->levelCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->image,
|
|
|
|
&vulkanTexture->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
imageCopy.imageExtent.width = w;
|
|
|
|
imageCopy.imageExtent.height = h;
|
|
|
|
imageCopy.imageExtent.depth = 1;
|
|
|
|
imageCopy.imageOffset.x = x;
|
|
|
|
imageCopy.imageOffset.y = y;
|
|
|
|
imageCopy.imageOffset.z = 0;
|
|
|
|
imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
imageCopy.imageSubresource.baseArrayLayer = 0;
|
|
|
|
imageCopy.imageSubresource.layerCount = 1;
|
|
|
|
imageCopy.imageSubresource.mipLevel = level;
|
|
|
|
imageCopy.bufferOffset = 0;
|
|
|
|
imageCopy.bufferRowLength = 0;
|
|
|
|
imageCopy.bufferImageHeight = 0;
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 01:03:26 +00:00
|
|
|
vulkanTexture->image,
|
|
|
|
AccessMap[vulkanTexture->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetTextureData3D(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t z,
|
|
|
|
uint32_t w,
|
|
|
|
uint32_t h,
|
|
|
|
uint32_t d,
|
|
|
|
uint32_t level,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
2020-12-19 02:38:15 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *vulkanTexture = (VulkanTexture*) texture;
|
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
|
uint8_t *mapPointer;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
|
|
|
|
|
2020-12-19 02:38:15 +00:00
|
|
|
vulkanResult = renderer->vkMapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->offset,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->size,
|
2020-12-19 02:38:15 +00:00
|
|
|
0,
|
|
|
|
(void**) &mapPointer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to map buffer memory!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(mapPointer, data, dataLength);
|
|
|
|
|
|
|
|
renderer->vkUnmapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory
|
2020-12-19 02:38:15 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
vulkanTexture->layerCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->levelCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->image,
|
|
|
|
&vulkanTexture->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
imageCopy.imageExtent.width = w;
|
|
|
|
imageCopy.imageExtent.height = h;
|
|
|
|
imageCopy.imageExtent.depth = d;
|
|
|
|
imageCopy.imageOffset.x = x;
|
|
|
|
imageCopy.imageOffset.y = y;
|
|
|
|
imageCopy.imageOffset.z = z;
|
|
|
|
imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
imageCopy.imageSubresource.baseArrayLayer = 0;
|
|
|
|
imageCopy.imageSubresource.layerCount = 1;
|
|
|
|
imageCopy.imageSubresource.mipLevel = level;
|
|
|
|
imageCopy.bufferOffset = 0;
|
|
|
|
imageCopy.bufferRowLength = 0;
|
|
|
|
imageCopy.bufferImageHeight = 0;
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 02:38:15 +00:00
|
|
|
vulkanTexture->image,
|
|
|
|
AccessMap[vulkanTexture->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetTextureDataCube(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t w,
|
|
|
|
uint32_t h,
|
|
|
|
REFRESH_CubeMapFace cubeMapFace,
|
|
|
|
uint32_t level,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
2020-12-19 02:38:15 +00:00
|
|
|
VkResult vulkanResult;
|
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *vulkanTexture = (VulkanTexture*) texture;
|
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
|
uint8_t *mapPointer;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
|
|
|
|
|
2020-12-19 02:38:15 +00:00
|
|
|
vulkanResult = renderer->vkMapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->offset,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->size,
|
2020-12-19 02:38:15 +00:00
|
|
|
0,
|
|
|
|
(void**) &mapPointer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to map buffer memory!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(mapPointer, data, dataLength);
|
|
|
|
|
|
|
|
renderer->vkUnmapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory
|
2020-12-19 02:38:15 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
vulkanTexture->layerCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->levelCount,
|
|
|
|
0,
|
|
|
|
vulkanTexture->image,
|
|
|
|
&vulkanTexture->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
imageCopy.imageExtent.width = w;
|
|
|
|
imageCopy.imageExtent.height = h;
|
|
|
|
imageCopy.imageExtent.depth = 1;
|
|
|
|
imageCopy.imageOffset.x = x;
|
|
|
|
imageCopy.imageOffset.y = y;
|
|
|
|
imageCopy.imageOffset.z = 0;
|
|
|
|
imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
imageCopy.imageSubresource.baseArrayLayer = cubeMapFace;
|
|
|
|
imageCopy.imageSubresource.layerCount = 1;
|
|
|
|
imageCopy.imageSubresource.mipLevel = level;
|
|
|
|
imageCopy.bufferOffset = 0;
|
|
|
|
imageCopy.bufferRowLength = 0; /* assumes tightly packed data */
|
|
|
|
imageCopy.bufferImageHeight = 0; /* assumes tightly packed data */
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 02:38:15 +00:00
|
|
|
vulkanTexture->image,
|
|
|
|
AccessMap[vulkanTexture->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetTextureDataYUV(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *y,
|
|
|
|
REFRESH_Texture *u,
|
|
|
|
REFRESH_Texture *v,
|
|
|
|
uint32_t yWidth,
|
|
|
|
uint32_t yHeight,
|
|
|
|
uint32_t uvWidth,
|
|
|
|
uint32_t uvHeight,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
2020-12-19 02:38:15 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture *tex;
|
|
|
|
uint8_t *dataPtr = (uint8_t*) data;
|
|
|
|
int32_t yDataLength = BytesPerImage(yWidth, yHeight, REFRESH_SURFACEFORMAT_R8);
|
|
|
|
int32_t uvDataLength = BytesPerImage(uvWidth, uvHeight, REFRESH_SURFACEFORMAT_R8);
|
|
|
|
VkBufferImageCopy imageCopy;
|
|
|
|
uint8_t *mapPointer;
|
|
|
|
VkResult vulkanResult;
|
|
|
|
|
2020-12-19 04:08:07 +00:00
|
|
|
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
|
|
|
|
|
2020-12-19 02:38:15 +00:00
|
|
|
/* Initialize values that are the same for Y, U, and V */
|
|
|
|
|
|
|
|
imageCopy.imageExtent.depth = 1;
|
|
|
|
imageCopy.imageOffset.x = 0;
|
|
|
|
imageCopy.imageOffset.y = 0;
|
|
|
|
imageCopy.imageOffset.z = 0;
|
|
|
|
imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
imageCopy.imageSubresource.baseArrayLayer = 0;
|
|
|
|
imageCopy.imageSubresource.layerCount = 1;
|
|
|
|
imageCopy.imageSubresource.mipLevel = 0;
|
|
|
|
imageCopy.bufferOffset = 0;
|
|
|
|
|
|
|
|
/* Y */
|
|
|
|
|
|
|
|
tex = (VulkanTexture*) y;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkMapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->offset,
|
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->size,
|
2020-12-19 02:38:15 +00:00
|
|
|
0,
|
|
|
|
(void**) &mapPointer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to map buffer memory!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(
|
|
|
|
mapPointer,
|
|
|
|
dataPtr,
|
|
|
|
yDataLength
|
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
tex->layerCount,
|
|
|
|
0,
|
|
|
|
tex->levelCount,
|
|
|
|
0,
|
|
|
|
tex->image,
|
|
|
|
&tex->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
imageCopy.imageExtent.width = yWidth;
|
|
|
|
imageCopy.imageExtent.height = yHeight;
|
|
|
|
imageCopy.bufferRowLength = yWidth;
|
|
|
|
imageCopy.bufferImageHeight = yHeight;
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 02:38:15 +00:00
|
|
|
tex->image,
|
|
|
|
AccessMap[tex->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
|
|
|
|
|
|
|
/* These apply to both U and V */
|
|
|
|
|
|
|
|
imageCopy.imageExtent.width = uvWidth;
|
|
|
|
imageCopy.imageExtent.height = uvHeight;
|
|
|
|
imageCopy.bufferRowLength = uvWidth;
|
|
|
|
imageCopy.bufferImageHeight = uvHeight;
|
|
|
|
|
|
|
|
/* U */
|
|
|
|
|
|
|
|
imageCopy.bufferOffset = yDataLength;
|
|
|
|
|
|
|
|
tex = (VulkanTexture*) u;
|
|
|
|
|
|
|
|
SDL_memcpy(
|
|
|
|
mapPointer + yDataLength,
|
|
|
|
dataPtr + yDataLength,
|
|
|
|
uvDataLength
|
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
tex->layerCount,
|
|
|
|
0,
|
|
|
|
tex->levelCount,
|
|
|
|
0,
|
|
|
|
tex->image,
|
|
|
|
&tex->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 02:38:15 +00:00
|
|
|
tex->image,
|
|
|
|
AccessMap[tex->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
|
|
|
|
|
|
|
/* V */
|
|
|
|
|
|
|
|
imageCopy.bufferOffset = yDataLength + uvDataLength;
|
|
|
|
|
|
|
|
tex = (VulkanTexture*) v;
|
|
|
|
|
|
|
|
SDL_memcpy(
|
|
|
|
mapPointer + yDataLength + uvDataLength,
|
|
|
|
dataPtr + yDataLength + uvDataLength,
|
|
|
|
uvDataLength
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->vkUnmapMemory(
|
|
|
|
renderer->logicalDevice,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory
|
2020-12-19 02:38:15 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
tex->layerCount,
|
|
|
|
0,
|
|
|
|
tex->levelCount,
|
|
|
|
0,
|
|
|
|
tex->image,
|
|
|
|
&tex->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdCopyBufferToImage(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-19 04:08:07 +00:00
|
|
|
renderer->textureStagingBuffer->subBuffers[0]->buffer,
|
2020-12-19 02:38:15 +00:00
|
|
|
tex->image,
|
|
|
|
AccessMap[tex->resourceAccessType].imageLayout,
|
|
|
|
1,
|
|
|
|
&imageCopy
|
|
|
|
));
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 20:37:54 +00:00
|
|
|
static void VULKAN_INTERNAL_SetBufferData(
|
|
|
|
REFRESH_Renderer* driverData,
|
|
|
|
REFRESH_Buffer* buffer,
|
|
|
|
uint32_t offsetInBytes,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
|
|
|
|
VulkanBuffer* vulkanBuffer = (VulkanBuffer*)buffer;
|
|
|
|
uint8_t* mapPointer;
|
|
|
|
VkResult vulkanResult;
|
2020-12-23 06:05:01 +00:00
|
|
|
uint32_t i;
|
2020-12-21 20:37:54 +00:00
|
|
|
|
2020-12-23 06:05:01 +00:00
|
|
|
#define CURIDX vulkanBuffer->currentSubBufferIndex
|
|
|
|
#define SUBBUF vulkanBuffer->subBuffers[CURIDX]
|
2020-12-21 20:37:54 +00:00
|
|
|
|
2020-12-23 06:05:01 +00:00
|
|
|
/* If buffer has not been bound this frame, set the first unbound index */
|
|
|
|
if (!vulkanBuffer->bound)
|
|
|
|
{
|
|
|
|
for (i = 0; i < vulkanBuffer->subBufferCount; i += 1)
|
|
|
|
{
|
|
|
|
if (vulkanBuffer->subBuffers[i]->bound == -1)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CURIDX = i;
|
|
|
|
}
|
|
|
|
else
|
2020-12-21 20:37:54 +00:00
|
|
|
{
|
2020-12-23 06:05:01 +00:00
|
|
|
REFRESH_LogError("Buffer already bound. It is an error to set vertex data after binding but before submitting.");
|
2020-12-21 20:37:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-23 06:05:01 +00:00
|
|
|
|
2020-12-21 20:37:54 +00:00
|
|
|
/* Map the memory and perform the copy */
|
|
|
|
vulkanResult = renderer->vkMapMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
SUBBUF->allocation->memory,
|
|
|
|
SUBBUF->offset,
|
|
|
|
SUBBUF->size,
|
|
|
|
0,
|
|
|
|
(void**)&mapPointer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to map buffer memory!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_memcpy(
|
|
|
|
mapPointer + offsetInBytes,
|
|
|
|
data,
|
|
|
|
dataLength
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->vkUnmapMemory(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
SUBBUF->allocation->memory
|
|
|
|
);
|
|
|
|
|
2020-12-23 06:05:01 +00:00
|
|
|
#undef CURIDX
|
2020-12-21 20:37:54 +00:00
|
|
|
#undef SUBBUF
|
|
|
|
}
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
static void VULKAN_SetVertexBufferData(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Buffer *buffer,
|
|
|
|
uint32_t offsetInBytes,
|
|
|
|
void* data,
|
|
|
|
uint32_t elementCount,
|
2020-12-21 20:37:54 +00:00
|
|
|
uint32_t vertexStride
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-21 20:37:54 +00:00
|
|
|
VULKAN_INTERNAL_SetBufferData(
|
|
|
|
driverData,
|
|
|
|
buffer,
|
|
|
|
offsetInBytes,
|
|
|
|
data,
|
|
|
|
elementCount * vertexStride
|
|
|
|
);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetIndexBufferData(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Buffer *buffer,
|
|
|
|
uint32_t offsetInBytes,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
2020-12-21 20:37:54 +00:00
|
|
|
VULKAN_INTERNAL_SetBufferData(
|
|
|
|
driverData,
|
|
|
|
buffer,
|
|
|
|
offsetInBytes,
|
|
|
|
data,
|
|
|
|
dataLength
|
|
|
|
);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-20 09:33:32 +00:00
|
|
|
static void VULKAN_PushVertexShaderParams(
|
|
|
|
REFRESH_Renderer *driverData,
|
|
|
|
void *data,
|
2020-12-23 21:11:09 +00:00
|
|
|
uint32_t elementCount
|
2020-12-20 09:33:32 +00:00
|
|
|
) {
|
2020-12-21 21:02:07 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
|
|
|
|
|
|
|
|
renderer->vertexUBOOffset += renderer->vertexUBOBlockIncrement;
|
2020-12-23 21:11:09 +00:00
|
|
|
renderer->vertexUBOBlockIncrement = renderer->currentGraphicsPipeline->vertexUBOBlockSize;
|
2020-12-21 21:02:07 +00:00
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
if (
|
|
|
|
renderer->vertexUBOOffset +
|
|
|
|
renderer->currentGraphicsPipeline->vertexUBOBlockSize >=
|
|
|
|
UBO_BUFFER_SIZE * renderer->frameIndex
|
|
|
|
) {
|
2020-12-21 21:02:07 +00:00
|
|
|
REFRESH_LogError("Vertex UBO overflow!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_SetBufferData(
|
|
|
|
driverData,
|
|
|
|
(REFRESH_Buffer*) renderer->vertexUBO,
|
|
|
|
renderer->vertexUBOOffset,
|
|
|
|
data,
|
2020-12-23 21:11:09 +00:00
|
|
|
elementCount * renderer->currentGraphicsPipeline->fragmentUBOBlockSize
|
2020-12-21 21:02:07 +00:00
|
|
|
);
|
2020-12-20 09:33:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_PushFragmentShaderParams(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
void *data,
|
2020-12-23 21:11:09 +00:00
|
|
|
uint32_t elementCount
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-21 21:02:07 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
|
|
|
|
|
|
|
|
renderer->fragmentUBOOffset += renderer->fragmentUBOBlockIncrement;
|
2020-12-23 21:11:09 +00:00
|
|
|
renderer->fragmentUBOBlockIncrement = renderer->currentGraphicsPipeline->fragmentUBOBlockSize;
|
2020-12-21 21:02:07 +00:00
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
if (
|
|
|
|
renderer->fragmentUBOOffset +
|
|
|
|
renderer->currentGraphicsPipeline->fragmentUBOBlockSize >=
|
|
|
|
UBO_BUFFER_SIZE * (renderer->frameIndex + 1)
|
|
|
|
) {
|
2020-12-21 21:02:07 +00:00
|
|
|
REFRESH_LogError("Fragment UBO overflow!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_SetBufferData(
|
|
|
|
driverData,
|
|
|
|
(REFRESH_Buffer*) renderer->fragmentUBO,
|
|
|
|
renderer->fragmentUBOOffset,
|
|
|
|
data,
|
2020-12-23 21:11:09 +00:00
|
|
|
elementCount * renderer->currentGraphicsPipeline->fragmentUBOBlockSize
|
2020-12-21 21:02:07 +00:00
|
|
|
);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetVertexSamplers(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-19 05:35:21 +00:00
|
|
|
REFRESH_GraphicsPipeline *pipeline,
|
|
|
|
REFRESH_Texture **pTextures,
|
|
|
|
REFRESH_Sampler **pSamplers
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-19 05:35:21 +00:00
|
|
|
/* TODO: we can defer and batch these */
|
|
|
|
|
|
|
|
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo;
|
|
|
|
VkDescriptorSet descriptorSet;
|
|
|
|
VkWriteDescriptorSet *writeDescriptorSets;
|
|
|
|
VkDescriptorImageInfo *descriptorImageInfos;
|
|
|
|
VulkanTexture *currentTexture;
|
|
|
|
VkSampler currentSampler;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) pipeline;
|
|
|
|
|
|
|
|
writeDescriptorSets = SDL_stack_alloc(VkWriteDescriptorSet, graphicsPipeline->vertexSamplerBindingCount);
|
|
|
|
descriptorImageInfos = SDL_stack_alloc(VkDescriptorImageInfo, graphicsPipeline->vertexSamplerBindingCount);
|
|
|
|
|
|
|
|
descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
descriptorSetAllocateInfo.pNext = NULL;
|
|
|
|
descriptorSetAllocateInfo.descriptorSetCount = 1;
|
|
|
|
descriptorSetAllocateInfo.descriptorPool = graphicsPipeline->descriptorPool;
|
|
|
|
descriptorSetAllocateInfo.pSetLayouts = &graphicsPipeline->vertexSamplerLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&descriptorSetAllocateInfo,
|
|
|
|
&descriptorSet
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < graphicsPipeline->vertexSamplerBindingCount; i += 1)
|
|
|
|
{
|
|
|
|
currentTexture = (VulkanTexture*) pTextures[i];
|
|
|
|
currentSampler = (VkSampler) pSamplers[i];
|
|
|
|
|
|
|
|
descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
descriptorImageInfos[i].imageView = currentTexture->view;
|
|
|
|
descriptorImageInfos[i].sampler = currentSampler;
|
|
|
|
|
|
|
|
writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
writeDescriptorSets[i].pNext = NULL;
|
|
|
|
writeDescriptorSets[i].dstSet = descriptorSet;
|
|
|
|
writeDescriptorSets[i].dstBinding = i;
|
|
|
|
writeDescriptorSets[i].dstArrayElement = 0;
|
|
|
|
writeDescriptorSets[i].descriptorCount = 1;
|
|
|
|
writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
writeDescriptorSets[i].pImageInfo = &descriptorImageInfos[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkUpdateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
graphicsPipeline->vertexSamplerBindingCount,
|
|
|
|
writeDescriptorSets,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
graphicsPipeline->vertexSamplerDescriptorSet = descriptorSet;
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
SDL_stack_free(writeDescriptorSets);
|
|
|
|
SDL_stack_free(descriptorImageInfos);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_SetFragmentSamplers(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-19 05:35:21 +00:00
|
|
|
REFRESH_GraphicsPipeline *pipeline,
|
|
|
|
REFRESH_Texture **pTextures,
|
|
|
|
REFRESH_Sampler **pSamplers
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-19 05:35:21 +00:00
|
|
|
/* TODO: we can defer and batch these */
|
|
|
|
|
|
|
|
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo;
|
|
|
|
VkDescriptorSet descriptorSet;
|
|
|
|
VkWriteDescriptorSet *writeDescriptorSets;
|
|
|
|
VkDescriptorImageInfo *descriptorImageInfos;
|
|
|
|
VulkanTexture *currentTexture;
|
|
|
|
VkSampler currentSampler;
|
|
|
|
uint32_t i;
|
|
|
|
|
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) pipeline;
|
|
|
|
|
|
|
|
writeDescriptorSets = SDL_stack_alloc(VkWriteDescriptorSet, graphicsPipeline->fragmentSamplerBindingCount);
|
|
|
|
descriptorImageInfos = SDL_stack_alloc(VkDescriptorImageInfo, graphicsPipeline->fragmentSamplerBindingCount);
|
|
|
|
|
|
|
|
descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
descriptorSetAllocateInfo.pNext = NULL;
|
|
|
|
descriptorSetAllocateInfo.descriptorSetCount = 1;
|
|
|
|
descriptorSetAllocateInfo.descriptorPool = graphicsPipeline->descriptorPool;
|
|
|
|
descriptorSetAllocateInfo.pSetLayouts = &graphicsPipeline->fragmentSamplerLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&descriptorSetAllocateInfo,
|
|
|
|
&descriptorSet
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < graphicsPipeline->fragmentSamplerBindingCount; i += 1)
|
|
|
|
{
|
|
|
|
currentTexture = (VulkanTexture*) pTextures[i];
|
|
|
|
currentSampler = (VkSampler) pSamplers[i];
|
|
|
|
|
|
|
|
descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
descriptorImageInfos[i].imageView = currentTexture->view;
|
|
|
|
descriptorImageInfos[i].sampler = currentSampler;
|
|
|
|
|
|
|
|
writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
|
|
writeDescriptorSets[i].pNext = NULL;
|
|
|
|
writeDescriptorSets[i].dstSet = descriptorSet;
|
|
|
|
writeDescriptorSets[i].dstBinding = i;
|
|
|
|
writeDescriptorSets[i].dstArrayElement = 0;
|
|
|
|
writeDescriptorSets[i].descriptorCount = 1;
|
|
|
|
writeDescriptorSets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
writeDescriptorSets[i].pImageInfo = &descriptorImageInfos[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkUpdateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
graphicsPipeline->fragmentSamplerBindingCount,
|
|
|
|
writeDescriptorSets,
|
|
|
|
0,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
graphicsPipeline->fragmentSamplerDescriptorSet = descriptorSet;
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
SDL_stack_free(writeDescriptorSets);
|
|
|
|
SDL_stack_free(descriptorImageInfos);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_GetTextureData2D(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t w,
|
|
|
|
uint32_t h,
|
|
|
|
uint32_t level,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_GetTextureDataCube(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t w,
|
|
|
|
uint32_t h,
|
|
|
|
REFRESH_CubeMapFace cubeMapFace,
|
|
|
|
uint32_t level,
|
|
|
|
void* data,
|
|
|
|
uint32_t dataLength
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeTexture(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Texture *texture
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeSampler(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Sampler *sampler
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeVertexBuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Buffer *buffer
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeIndexBuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Buffer *buffer
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeColorTarget(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_ColorTarget *colorTarget
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeDepthStencilTarget(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_DepthStencilTarget *depthStencilTarget
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeFramebuffer(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_Framebuffer *frameBuffer
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeShaderModule(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_ShaderModule *shaderModule
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeRenderPass(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_RenderPass *renderPass
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_AddDisposeGraphicsPipeline(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_GraphicsPipeline *graphicsPipeline
|
|
|
|
) {
|
|
|
|
SDL_assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_BeginRenderPass(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_RenderPass *renderPass,
|
|
|
|
REFRESH_Framebuffer *framebuffer,
|
|
|
|
REFRESH_Rect renderArea,
|
2020-12-20 08:05:12 +00:00
|
|
|
REFRESH_Color *pColorClearValues,
|
|
|
|
uint32_t colorClearCount,
|
|
|
|
REFRESH_DepthStencilValue *depthStencilClearValue
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-20 08:05:12 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
2020-12-23 07:17:09 +00:00
|
|
|
VulkanFramebuffer *vulkanFramebuffer = (VulkanFramebuffer*) framebuffer;
|
2020-12-20 08:05:12 +00:00
|
|
|
VkClearValue *clearValues;
|
|
|
|
uint32_t i;
|
2020-12-23 07:17:09 +00:00
|
|
|
uint32_t clearCount = colorClearCount;
|
|
|
|
VkImageAspectFlags depthAspectFlags;
|
|
|
|
|
|
|
|
/* Layout transitions */
|
|
|
|
|
|
|
|
for (i = 0; i < vulkanFramebuffer->colorTargetCount; i += 1)
|
|
|
|
{
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
vulkanFramebuffer->colorTargets[i]->layer,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
vulkanFramebuffer->colorTargets[i]->texture->image,
|
|
|
|
&vulkanFramebuffer->colorTargets[i]->texture->resourceAccessType
|
|
|
|
);
|
|
|
|
}
|
2020-12-20 08:05:12 +00:00
|
|
|
|
|
|
|
if (depthStencilClearValue != NULL)
|
|
|
|
{
|
2020-12-23 07:17:09 +00:00
|
|
|
depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
|
if (DepthFormatContainsStencil(
|
|
|
|
vulkanFramebuffer->depthStencilTarget->texture->format
|
|
|
|
)) {
|
|
|
|
depthAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_WRITE,
|
|
|
|
depthAspectFlags,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
vulkanFramebuffer->depthStencilTarget->texture->image,
|
|
|
|
&vulkanFramebuffer->depthStencilTarget->texture->resourceAccessType
|
|
|
|
);
|
|
|
|
|
|
|
|
clearCount += 1;
|
2020-12-20 08:05:12 +00:00
|
|
|
}
|
|
|
|
|
2020-12-23 07:17:09 +00:00
|
|
|
/* Set clear values */
|
|
|
|
|
|
|
|
clearValues = SDL_stack_alloc(VkClearValue, clearCount);
|
2020-12-20 08:05:12 +00:00
|
|
|
|
|
|
|
for (i = 0; i < colorClearCount; i += 1)
|
|
|
|
{
|
2020-12-23 05:53:39 +00:00
|
|
|
clearValues[i].color.float32[0] = pColorClearValues[i].r / 255.0f;
|
|
|
|
clearValues[i].color.float32[1] = pColorClearValues[i].g / 255.0f;
|
|
|
|
clearValues[i].color.float32[2] = pColorClearValues[i].b / 255.0f;
|
|
|
|
clearValues[i].color.float32[3] = pColorClearValues[i].a / 255.0f;
|
2020-12-20 08:05:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (depthStencilClearValue != NULL)
|
|
|
|
{
|
|
|
|
clearValues[colorClearCount].depthStencil.depth =
|
|
|
|
depthStencilClearValue->depth;
|
|
|
|
clearValues[colorClearCount].depthStencil.stencil =
|
|
|
|
depthStencilClearValue->stencil;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkRenderPassBeginInfo renderPassBeginInfo;
|
|
|
|
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
|
|
renderPassBeginInfo.pNext = NULL;
|
|
|
|
renderPassBeginInfo.renderPass = (VkRenderPass) renderPass;
|
2020-12-23 07:17:09 +00:00
|
|
|
renderPassBeginInfo.framebuffer = vulkanFramebuffer->framebuffer;
|
2020-12-20 08:05:12 +00:00
|
|
|
renderPassBeginInfo.renderArea.extent.width = renderArea.w;
|
|
|
|
renderPassBeginInfo.renderArea.extent.height = renderArea.h;
|
|
|
|
renderPassBeginInfo.renderArea.offset.x = renderArea.x;
|
|
|
|
renderPassBeginInfo.renderArea.offset.y = renderArea.y;
|
|
|
|
renderPassBeginInfo.pClearValues = clearValues;
|
2020-12-23 07:17:09 +00:00
|
|
|
renderPassBeginInfo.clearValueCount = clearCount;
|
2020-12-20 08:05:12 +00:00
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdBeginRenderPass(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
&renderPassBeginInfo,
|
|
|
|
VK_SUBPASS_CONTENTS_INLINE
|
|
|
|
));
|
|
|
|
|
|
|
|
SDL_stack_free(clearValues);
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_EndRenderPass(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
2020-12-20 08:05:53 +00:00
|
|
|
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdEndRenderPass(
|
|
|
|
renderer->currentCommandBuffer
|
|
|
|
));
|
2020-12-23 07:17:09 +00:00
|
|
|
|
|
|
|
renderer->currentGraphicsPipeline = NULL;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_BindGraphicsPipeline(
|
2020-12-17 08:19:02 +00:00
|
|
|
REFRESH_Renderer *driverData,
|
2020-12-17 01:23:49 +00:00
|
|
|
REFRESH_GraphicsPipeline *graphicsPipeline
|
|
|
|
) {
|
2020-12-20 07:17:55 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanGraphicsPipeline* pipeline = (VulkanGraphicsPipeline*) graphicsPipeline;
|
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
/* bind dummy samplers */
|
|
|
|
if (pipeline->vertexSamplerBindingCount == 0)
|
|
|
|
{
|
|
|
|
pipeline->vertexSamplerDescriptorSet = renderer->emptyVertexSamplerDescriptorSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pipeline->fragmentSamplerBindingCount == 0)
|
|
|
|
{
|
|
|
|
pipeline->fragmentSamplerDescriptorSet = renderer->emptyFragmentSamplerDescriptorSet;
|
|
|
|
}
|
|
|
|
|
2020-12-20 07:17:55 +00:00
|
|
|
RECORD_CMD(renderer->vkCmdBindPipeline(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
pipeline->pipeline
|
|
|
|
));
|
2020-12-23 06:56:26 +00:00
|
|
|
|
|
|
|
renderer->currentGraphicsPipeline = pipeline;
|
2020-12-17 01:23:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
static void VULKAN_INTERNAL_MarkAsBound(
|
|
|
|
VulkanRenderer* renderer,
|
|
|
|
VulkanBuffer* buf
|
|
|
|
) {
|
2020-12-23 06:05:01 +00:00
|
|
|
VulkanSubBuffer *subbuf = buf->subBuffers[buf->currentSubBufferIndex];
|
|
|
|
subbuf->bound = renderer->frameIndex;
|
2020-12-21 23:44:43 +00:00
|
|
|
|
|
|
|
/* Don't rebind a bound buffer */
|
|
|
|
if (buf->bound) return;
|
|
|
|
|
|
|
|
buf->bound = 1;
|
|
|
|
|
|
|
|
if (renderer->buffersInUseCount == renderer->buffersInUseCapacity)
|
|
|
|
{
|
|
|
|
renderer->buffersInUseCapacity *= 2;
|
|
|
|
renderer->buffersInUse = SDL_realloc(
|
|
|
|
renderer->buffersInUse,
|
|
|
|
sizeof(VulkanBuffer*) * renderer->buffersInUseCapacity
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->buffersInUse[renderer->buffersInUseCount] = buf;
|
|
|
|
renderer->buffersInUseCount += 1;
|
|
|
|
}
|
|
|
|
|
2020-12-20 07:31:55 +00:00
|
|
|
static void VULKAN_BindVertexBuffers(
|
|
|
|
REFRESH_Renderer *driverData,
|
|
|
|
uint32_t firstBinding,
|
|
|
|
uint32_t bindingCount,
|
|
|
|
REFRESH_Buffer **pBuffers,
|
|
|
|
uint64_t *pOffsets
|
|
|
|
) {
|
|
|
|
VkBuffer *buffers = SDL_stack_alloc(VkBuffer, bindingCount);
|
|
|
|
VulkanBuffer* currentBuffer;
|
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
2020-12-21 20:37:54 +00:00
|
|
|
uint32_t i;
|
2020-12-20 07:31:55 +00:00
|
|
|
|
2020-12-21 20:37:54 +00:00
|
|
|
for (i = 0; i < bindingCount; i += 1)
|
2020-12-20 07:31:55 +00:00
|
|
|
{
|
|
|
|
currentBuffer = (VulkanBuffer*) pBuffers[i];
|
2020-12-23 07:46:37 +00:00
|
|
|
buffers[i] = currentBuffer->subBuffers[currentBuffer->currentSubBufferIndex]->buffer;
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_MarkAsBound(renderer, currentBuffer);
|
2020-12-20 07:31:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdBindVertexBuffers(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
firstBinding,
|
|
|
|
bindingCount,
|
|
|
|
buffers,
|
|
|
|
pOffsets
|
|
|
|
));
|
|
|
|
|
|
|
|
SDL_stack_free(buffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void VULKAN_BindIndexBuffer(
|
|
|
|
REFRESH_Renderer *driverData,
|
|
|
|
REFRESH_Buffer *buffer,
|
|
|
|
uint64_t offset,
|
|
|
|
REFRESH_IndexElementSize indexElementSize
|
|
|
|
) {
|
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanBuffer* vulkanBuffer = (VulkanBuffer*) buffer;
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_MarkAsBound(renderer, vulkanBuffer);
|
|
|
|
|
2020-12-20 07:31:55 +00:00
|
|
|
RECORD_CMD(renderer->vkCmdBindIndexBuffer(
|
|
|
|
renderer->currentCommandBuffer,
|
2020-12-21 23:44:43 +00:00
|
|
|
vulkanBuffer->subBuffers[renderer->frameIndex]->buffer,
|
2020-12-20 07:31:55 +00:00
|
|
|
offset,
|
|
|
|
RefreshToVK_IndexType[indexElementSize]
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2020-12-22 02:54:36 +00:00
|
|
|
static void VULKAN_QueuePresent(
|
2020-12-21 23:44:43 +00:00
|
|
|
REFRESH_Renderer* driverData,
|
2020-12-22 02:54:36 +00:00
|
|
|
REFRESH_TextureSlice* textureSlice,
|
2020-12-21 23:44:43 +00:00
|
|
|
REFRESH_Rect* sourceRectangle,
|
|
|
|
REFRESH_Rect* destinationRectangle
|
2020-12-17 04:19:11 +00:00
|
|
|
) {
|
2020-12-21 23:44:43 +00:00
|
|
|
VkResult acquireResult;
|
|
|
|
uint32_t swapChainImageIndex;
|
2020-12-17 04:19:11 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
REFRESH_Rect srcRect;
|
|
|
|
REFRESH_Rect dstRect;
|
|
|
|
VkImageBlit blit;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-22 02:54:36 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*) driverData;
|
|
|
|
VulkanTexture* vulkanTexture = (VulkanTexture*) textureSlice->texture;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (renderer->headless)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-22 02:54:36 +00:00
|
|
|
REFRESH_LogError("Cannot call QueuePresent in headless mode!");
|
2020-12-21 23:44:43 +00:00
|
|
|
return;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
acquireResult = renderer->vkAcquireNextImageKHR(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->swapChain,
|
|
|
|
UINT64_MAX,
|
|
|
|
renderer->imageAvailableSemaphore,
|
|
|
|
VK_NULL_HANDLE,
|
|
|
|
&swapChainImageIndex
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR)
|
|
|
|
{
|
|
|
|
/* Failed to acquire swapchain image, mark that we need a new one */
|
|
|
|
renderer->needNewSwapChain = 1;
|
|
|
|
return;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->shouldPresent = 1;
|
|
|
|
renderer->swapChainImageAcquired = 1;
|
|
|
|
renderer->currentSwapChainIndex = swapChainImageIndex;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (sourceRectangle != NULL)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
srcRect = *sourceRectangle;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
2020-12-21 23:44:43 +00:00
|
|
|
else
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
srcRect.x = 0;
|
|
|
|
srcRect.y = 0;
|
|
|
|
srcRect.w = vulkanTexture->dimensions.width;
|
|
|
|
srcRect.h = vulkanTexture->dimensions.height;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (destinationRectangle != NULL)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
dstRect = *destinationRectangle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dstRect.x = 0;
|
|
|
|
dstRect.y = 0;
|
|
|
|
dstRect.w = renderer->swapChainExtent.width;
|
|
|
|
dstRect.h = renderer->swapChainExtent.height;
|
|
|
|
}
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Blit the framebuffer! */
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_READ,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
vulkanTexture->image,
|
|
|
|
&vulkanTexture->resourceAccessType
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_TRANSFER_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
renderer->swapChainImages[swapChainImageIndex],
|
|
|
|
&renderer->swapChainResourceAccessTypes[swapChainImageIndex]
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
blit.srcOffsets[0].x = srcRect.x;
|
|
|
|
blit.srcOffsets[0].y = srcRect.y;
|
|
|
|
blit.srcOffsets[0].z = 0;
|
|
|
|
blit.srcOffsets[1].x = srcRect.x + srcRect.w;
|
|
|
|
blit.srcOffsets[1].y = srcRect.y + srcRect.h;
|
|
|
|
blit.srcOffsets[1].z = 1;
|
|
|
|
|
|
|
|
blit.srcSubresource.mipLevel = 0;
|
|
|
|
blit.srcSubresource.baseArrayLayer = 0;
|
|
|
|
blit.srcSubresource.layerCount = 1;
|
|
|
|
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
|
|
|
blit.dstOffsets[0].x = dstRect.x;
|
|
|
|
blit.dstOffsets[0].y = dstRect.y;
|
|
|
|
blit.dstOffsets[0].z = 0;
|
|
|
|
blit.dstOffsets[1].x = dstRect.x + dstRect.w;
|
|
|
|
blit.dstOffsets[1].y = dstRect.y + dstRect.h;
|
|
|
|
blit.dstOffsets[1].z = 1;
|
|
|
|
|
|
|
|
blit.dstSubresource.mipLevel = 0;
|
2020-12-22 02:54:36 +00:00
|
|
|
blit.dstSubresource.baseArrayLayer = textureSlice->layer;
|
2020-12-21 23:44:43 +00:00
|
|
|
blit.dstSubresource.layerCount = 1;
|
|
|
|
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
|
|
|
RECORD_CMD(renderer->vkCmdBlitImage(
|
|
|
|
renderer->currentCommandBuffer,
|
|
|
|
vulkanTexture->image,
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
|
|
|
renderer->swapChainImages[swapChainImageIndex],
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
1,
|
|
|
|
&blit,
|
|
|
|
VK_FILTER_LINEAR
|
|
|
|
));
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_PRESENT,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
renderer->swapChainImages[swapChainImageIndex],
|
|
|
|
&renderer->swapChainResourceAccessTypes[swapChainImageIndex]
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
|
|
|
renderer,
|
|
|
|
RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE,
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
0,
|
|
|
|
vulkanTexture->image,
|
|
|
|
&vulkanTexture->resourceAccessType
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
static void VULKAN_Submit(
|
|
|
|
REFRESH_Renderer *driverData
|
2020-12-17 03:50:31 +00:00
|
|
|
) {
|
2020-12-21 23:44:43 +00:00
|
|
|
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
|
|
|
|
VkSubmitInfo submitInfo;
|
|
|
|
VkResult vulkanResult, presentResult = VK_SUCCESS;
|
2020-12-23 06:05:01 +00:00
|
|
|
uint32_t i, j;
|
2020-12-21 23:44:43 +00:00
|
|
|
uint8_t present;
|
|
|
|
|
|
|
|
VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
|
|
VkPresentInfoKHR presentInfo;
|
|
|
|
|
|
|
|
present = !renderer->headless && renderer->shouldPresent;
|
|
|
|
|
2020-12-22 02:34:57 +00:00
|
|
|
if (renderer->activeCommandBufferCount <= 1 && renderer->numActiveCommands == 0)
|
|
|
|
{
|
|
|
|
/* No commands recorded, bailing out */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (renderer->currentCommandBuffer != NULL)
|
|
|
|
{
|
|
|
|
VULKAN_INTERNAL_EndCommandBuffer(renderer);
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
|
|
submitInfo.pNext = NULL;
|
|
|
|
submitInfo.commandBufferCount = renderer->activeCommandBufferCount;
|
|
|
|
submitInfo.pCommandBuffers = renderer->activeCommandBuffers;
|
|
|
|
|
|
|
|
if (present)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
submitInfo.waitSemaphoreCount = 1;
|
|
|
|
submitInfo.pWaitSemaphores = &renderer->imageAvailableSemaphore;
|
|
|
|
submitInfo.pWaitDstStageMask = &waitStages;
|
|
|
|
submitInfo.signalSemaphoreCount = 1;
|
|
|
|
submitInfo.pSignalSemaphores = &renderer->renderFinishedSemaphore;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
submitInfo.waitSemaphoreCount = 0;
|
|
|
|
submitInfo.pWaitSemaphores = NULL;
|
|
|
|
submitInfo.pWaitDstStageMask = NULL;
|
|
|
|
submitInfo.signalSemaphoreCount = 0;
|
|
|
|
submitInfo.pSignalSemaphores = NULL;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Wait for the previous submission to complete */
|
|
|
|
vulkanResult = renderer->vkWaitForFences(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
1,
|
|
|
|
&renderer->inFlightFence,
|
|
|
|
VK_TRUE,
|
|
|
|
UINT64_MAX
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkWaitForFences", vulkanResult);
|
|
|
|
return;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_PerformDeferredDestroys(renderer);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->frameIndex = (renderer->frameIndex + 1) % 2;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Mark sub buffers of previously submitted buffers as unbound */
|
|
|
|
for (i = 0; i < renderer->submittedBufferCount; i += 1)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
if (renderer->submittedBuffers[i] != NULL)
|
|
|
|
{
|
2020-12-23 06:05:01 +00:00
|
|
|
renderer->submittedBuffers[i]->boundSubmitted = 0;
|
|
|
|
|
|
|
|
for (j = 0; j < renderer->submittedBuffers[i]->subBufferCount; j += 1)
|
|
|
|
{
|
|
|
|
if (renderer->submittedBuffers[i]->subBuffers[j]->bound == renderer->frameIndex)
|
|
|
|
{
|
|
|
|
renderer->submittedBuffers[i]->subBuffers[j]->bound = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedBuffers[i] = NULL;
|
|
|
|
}
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedBufferCount = 0;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Mark currently bound buffers as submitted buffers */
|
|
|
|
if (renderer->buffersInUseCount > renderer->submittedBufferCapacity)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedBuffers = SDL_realloc(
|
|
|
|
renderer->submittedBuffers,
|
|
|
|
sizeof(VulkanBuffer*) * renderer->buffersInUseCount
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->submittedBufferCapacity = renderer->buffersInUseCount;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
for (i = 0; i < renderer->buffersInUseCount; i += 1)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
if (renderer->buffersInUse[i] != NULL)
|
|
|
|
{
|
|
|
|
renderer->buffersInUse[i]->bound = 0;
|
|
|
|
renderer->buffersInUse[i]->boundSubmitted = 1;
|
|
|
|
|
|
|
|
renderer->submittedBuffers[i] = renderer->buffersInUse[i];
|
|
|
|
renderer->buffersInUse[i] = NULL;
|
|
|
|
}
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedBufferCount = renderer->buffersInUseCount;
|
|
|
|
renderer->buffersInUseCount = 0;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Reset the previously submitted command buffers */
|
|
|
|
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1)
|
|
|
|
{
|
|
|
|
vulkanResult = renderer->vkResetCommandBuffer(
|
|
|
|
renderer->submittedCommandBuffers[i],
|
|
|
|
VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT
|
|
|
|
);
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkResetCommandBuffer", vulkanResult);
|
|
|
|
}
|
|
|
|
}
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Mark the previously submitted command buffers as inactive */
|
|
|
|
for (i = 0; i < renderer->submittedCommandBufferCount; i += 1)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->inactiveCommandBuffers[renderer->inactiveCommandBufferCount] = renderer->submittedCommandBuffers[i];
|
|
|
|
renderer->inactiveCommandBufferCount += 1;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedCommandBufferCount = 0;
|
|
|
|
|
|
|
|
/* Prepare the command buffer fence for submission */
|
|
|
|
renderer->vkResetFences(
|
2020-12-17 03:50:31 +00:00
|
|
|
renderer->logicalDevice,
|
2020-12-21 23:44:43 +00:00
|
|
|
1,
|
|
|
|
&renderer->inFlightFence
|
2020-12-17 03:50:31 +00:00
|
|
|
);
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Submit the commands, finally. */
|
|
|
|
vulkanResult = renderer->vkQueueSubmit(
|
|
|
|
renderer->graphicsQueue,
|
|
|
|
1,
|
|
|
|
&submitInfo,
|
|
|
|
renderer->inFlightFence
|
2020-12-17 03:50:31 +00:00
|
|
|
);
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (vulkanResult != VK_SUCCESS)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
LogVulkanResult("vkQueueSubmit", vulkanResult);
|
|
|
|
return;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Mark active command buffers as submitted */
|
|
|
|
for (i = 0; i < renderer->activeCommandBufferCount; i += 1)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = renderer->activeCommandBuffers[i];
|
|
|
|
renderer->submittedCommandBufferCount += 1;
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->activeCommandBufferCount = 0;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Reset UBOs */
|
|
|
|
|
|
|
|
renderer->vertexUBOOffset = UBO_BUFFER_SIZE * renderer->frameIndex;
|
|
|
|
renderer->vertexUBOBlockIncrement = 0;
|
|
|
|
renderer->fragmentUBOOffset = UBO_BUFFER_SIZE * renderer->frameIndex;
|
|
|
|
renderer->fragmentUBOBlockIncrement = 0;
|
|
|
|
|
|
|
|
/* Present, if applicable */
|
|
|
|
|
|
|
|
if (present)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
|
|
presentInfo.pNext = NULL;
|
|
|
|
presentInfo.waitSemaphoreCount = 1;
|
|
|
|
presentInfo.pWaitSemaphores = &renderer->renderFinishedSemaphore;
|
|
|
|
presentInfo.swapchainCount = 1;
|
|
|
|
presentInfo.pSwapchains = &renderer->swapChain;
|
|
|
|
presentInfo.pImageIndices = &renderer->currentSwapChainIndex;
|
|
|
|
presentInfo.pResults = NULL;
|
2020-12-17 03:50:31 +00:00
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
presentResult = renderer->vkQueuePresentKHR(
|
|
|
|
renderer->presentQueue,
|
|
|
|
&presentInfo
|
2020-12-17 03:50:31 +00:00
|
|
|
);
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
if (renderer->needNewSwapChain)
|
2020-12-17 03:50:31 +00:00
|
|
|
{
|
2020-12-21 23:44:43 +00:00
|
|
|
VULKAN_INTERNAL_RecreateSwapchain(renderer);
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->swapChainImageAcquired = 0;
|
|
|
|
renderer->shouldPresent = 0;
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_BeginCommandBuffer(renderer);
|
2020-12-17 03:50:31 +00:00
|
|
|
}
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
/* Device instantiation */
|
|
|
|
|
|
|
|
static inline uint8_t VULKAN_INTERNAL_SupportsExtension(
|
|
|
|
const char *ext,
|
|
|
|
VkExtensionProperties *availableExtensions,
|
|
|
|
uint32_t numAvailableExtensions
|
|
|
|
) {
|
|
|
|
uint32_t i;
|
|
|
|
for (i = 0; i < numAvailableExtensions; i += 1)
|
|
|
|
{
|
|
|
|
if (SDL_strcmp(ext, availableExtensions[i].extensionName) == 0)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CheckInstanceExtensions(
|
|
|
|
const char **requiredExtensions,
|
|
|
|
uint32_t requiredExtensionsLength,
|
|
|
|
uint8_t *supportsDebugUtils
|
|
|
|
) {
|
|
|
|
uint32_t extensionCount, i;
|
|
|
|
VkExtensionProperties *availableExtensions;
|
|
|
|
uint8_t allExtensionsSupported = 1;
|
|
|
|
|
|
|
|
vkEnumerateInstanceExtensionProperties(
|
|
|
|
NULL,
|
|
|
|
&extensionCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
availableExtensions = SDL_stack_alloc(
|
|
|
|
VkExtensionProperties,
|
|
|
|
extensionCount
|
|
|
|
);
|
|
|
|
vkEnumerateInstanceExtensionProperties(
|
|
|
|
NULL,
|
|
|
|
&extensionCount,
|
|
|
|
availableExtensions
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < requiredExtensionsLength; i += 1)
|
|
|
|
{
|
|
|
|
if (!VULKAN_INTERNAL_SupportsExtension(
|
|
|
|
requiredExtensions[i],
|
|
|
|
availableExtensions,
|
|
|
|
extensionCount
|
|
|
|
)) {
|
|
|
|
allExtensionsSupported = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is optional, but nice to have! */
|
|
|
|
*supportsDebugUtils = VULKAN_INTERNAL_SupportsExtension(
|
|
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
|
|
|
availableExtensions,
|
|
|
|
extensionCount
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free(availableExtensions);
|
|
|
|
return allExtensionsSupported;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CheckValidationLayers(
|
|
|
|
const char** validationLayers,
|
|
|
|
uint32_t validationLayersLength
|
|
|
|
) {
|
|
|
|
uint32_t layerCount;
|
|
|
|
VkLayerProperties *availableLayers;
|
|
|
|
uint32_t i, j;
|
2020-12-18 00:39:25 +00:00
|
|
|
uint8_t layerFound = 0;
|
2020-12-17 03:28:02 +00:00
|
|
|
|
|
|
|
vkEnumerateInstanceLayerProperties(&layerCount, NULL);
|
|
|
|
availableLayers = SDL_stack_alloc(VkLayerProperties, layerCount);
|
|
|
|
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
|
|
|
|
|
|
|
|
for (i = 0; i < validationLayersLength; i += 1)
|
|
|
|
{
|
|
|
|
layerFound = 0;
|
|
|
|
|
|
|
|
for (j = 0; j < layerCount; j += 1)
|
|
|
|
{
|
|
|
|
if (SDL_strcmp(validationLayers[i], availableLayers[j].layerName) == 0)
|
|
|
|
{
|
|
|
|
layerFound = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!layerFound)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_stack_free(availableLayers);
|
|
|
|
return layerFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CreateInstance(
|
|
|
|
VulkanRenderer *renderer,
|
2020-12-17 02:12:20 +00:00
|
|
|
void *deviceWindowHandle
|
2020-12-17 03:28:02 +00:00
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
VkApplicationInfo appInfo;
|
|
|
|
const char **instanceExtensionNames;
|
|
|
|
uint32_t instanceExtensionCount;
|
|
|
|
VkInstanceCreateInfo createInfo;
|
|
|
|
static const char *layerNames[] = { "VK_LAYER_KHRONOS_validation" };
|
|
|
|
|
|
|
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
|
|
|
appInfo.pNext = NULL;
|
|
|
|
appInfo.pApplicationName = NULL;
|
|
|
|
appInfo.applicationVersion = 0;
|
|
|
|
appInfo.pEngineName = "REFRESH";
|
|
|
|
appInfo.engineVersion = REFRESH_COMPILED_VERSION;
|
|
|
|
appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
|
|
|
|
|
|
if (!SDL_Vulkan_GetInstanceExtensions(
|
|
|
|
(SDL_Window*) deviceWindowHandle,
|
|
|
|
&instanceExtensionCount,
|
|
|
|
NULL
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
|
|
|
|
SDL_GetError()
|
|
|
|
);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extra space for the following extensions:
|
|
|
|
* VK_KHR_get_physical_device_properties2
|
|
|
|
* VK_EXT_debug_utils
|
|
|
|
*/
|
|
|
|
instanceExtensionNames = SDL_stack_alloc(
|
|
|
|
const char*,
|
|
|
|
instanceExtensionCount + 2
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!SDL_Vulkan_GetInstanceExtensions(
|
|
|
|
(SDL_Window*) deviceWindowHandle,
|
|
|
|
&instanceExtensionCount,
|
|
|
|
instanceExtensionNames
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"SDL_Vulkan_GetInstanceExtensions(): %s",
|
|
|
|
SDL_GetError()
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free((char*) instanceExtensionNames);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Core since 1.1 */
|
|
|
|
instanceExtensionNames[instanceExtensionCount++] =
|
|
|
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CheckInstanceExtensions(
|
|
|
|
instanceExtensionNames,
|
|
|
|
instanceExtensionCount,
|
|
|
|
&renderer->supportsDebugUtils
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"Required Vulkan instance extensions not supported"
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free((char*) instanceExtensionNames);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (renderer->supportsDebugUtils)
|
|
|
|
{
|
|
|
|
/* Append the debug extension to the end */
|
|
|
|
instanceExtensionNames[instanceExtensionCount++] =
|
|
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REFRESH_LogWarn(
|
|
|
|
"%s is not supported!",
|
|
|
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
|
|
createInfo.pNext = NULL;
|
|
|
|
createInfo.flags = 0;
|
|
|
|
createInfo.pApplicationInfo = &appInfo;
|
|
|
|
createInfo.ppEnabledLayerNames = layerNames;
|
|
|
|
createInfo.enabledExtensionCount = instanceExtensionCount;
|
|
|
|
createInfo.ppEnabledExtensionNames = instanceExtensionNames;
|
|
|
|
if (renderer->debugMode)
|
|
|
|
{
|
|
|
|
createInfo.enabledLayerCount = SDL_arraysize(layerNames);
|
|
|
|
if (!VULKAN_INTERNAL_CheckValidationLayers(
|
|
|
|
layerNames,
|
|
|
|
createInfo.enabledLayerCount
|
|
|
|
)) {
|
|
|
|
REFRESH_LogWarn("Validation layers not found, continuing without validation");
|
|
|
|
createInfo.enabledLayerCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
createInfo.enabledLayerCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkCreateInstance failed: %s",
|
|
|
|
VkErrorMessages(vulkanResult)
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free((char*) instanceExtensionNames);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_stack_free((char*) instanceExtensionNames);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CheckDeviceExtensions(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkPhysicalDevice physicalDevice,
|
|
|
|
const char** requiredExtensions,
|
|
|
|
uint32_t requiredExtensionsLength
|
|
|
|
) {
|
|
|
|
uint32_t extensionCount, i;
|
|
|
|
VkExtensionProperties *availableExtensions;
|
|
|
|
uint8_t allExtensionsSupported = 1;
|
|
|
|
|
|
|
|
renderer->vkEnumerateDeviceExtensionProperties(
|
|
|
|
physicalDevice,
|
|
|
|
NULL,
|
|
|
|
&extensionCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
availableExtensions = SDL_stack_alloc(
|
|
|
|
VkExtensionProperties,
|
|
|
|
extensionCount
|
|
|
|
);
|
|
|
|
renderer->vkEnumerateDeviceExtensionProperties(
|
|
|
|
physicalDevice,
|
|
|
|
NULL,
|
|
|
|
&extensionCount,
|
|
|
|
availableExtensions
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < requiredExtensionsLength; i += 1)
|
|
|
|
{
|
|
|
|
if (!VULKAN_INTERNAL_SupportsExtension(
|
|
|
|
requiredExtensions[i],
|
|
|
|
availableExtensions,
|
|
|
|
extensionCount
|
|
|
|
)) {
|
|
|
|
allExtensionsSupported = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_stack_free(availableExtensions);
|
|
|
|
return allExtensionsSupported;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_IsDeviceSuitable(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
VkPhysicalDevice physicalDevice,
|
|
|
|
const char** requiredExtensionNames,
|
|
|
|
uint32_t requiredExtensionNamesLength,
|
|
|
|
VkSurfaceKHR surface,
|
|
|
|
QueueFamilyIndices *queueFamilyIndices,
|
|
|
|
uint8_t *isIdeal
|
|
|
|
) {
|
|
|
|
uint32_t queueFamilyCount, i;
|
|
|
|
SwapChainSupportDetails swapChainSupportDetails;
|
|
|
|
VkQueueFamilyProperties *queueProps;
|
|
|
|
VkBool32 supportsPresent;
|
|
|
|
uint8_t querySuccess, foundSuitableDevice = 0;
|
|
|
|
VkPhysicalDeviceProperties deviceProperties;
|
|
|
|
|
|
|
|
queueFamilyIndices->graphicsFamily = UINT32_MAX;
|
|
|
|
queueFamilyIndices->presentFamily = UINT32_MAX;
|
|
|
|
*isIdeal = 0;
|
|
|
|
|
|
|
|
/* Note: If no dedicated device exists,
|
|
|
|
* one that supports our features would be fine
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CheckDeviceExtensions(
|
|
|
|
renderer,
|
|
|
|
physicalDevice,
|
|
|
|
requiredExtensionNames,
|
|
|
|
requiredExtensionNamesLength
|
|
|
|
)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
|
|
physicalDevice,
|
|
|
|
&queueFamilyCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
/* FIXME: Need better structure for checking vs storing support details */
|
|
|
|
querySuccess = VULKAN_INTERNAL_QuerySwapChainSupport(
|
|
|
|
renderer,
|
|
|
|
physicalDevice,
|
|
|
|
surface,
|
|
|
|
&swapChainSupportDetails
|
|
|
|
);
|
|
|
|
SDL_free(swapChainSupportDetails.formats);
|
|
|
|
SDL_free(swapChainSupportDetails.presentModes);
|
|
|
|
if ( querySuccess == 0 ||
|
|
|
|
swapChainSupportDetails.formatsLength == 0 ||
|
|
|
|
swapChainSupportDetails.presentModesLength == 0 )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
queueProps = (VkQueueFamilyProperties*) SDL_stack_alloc(
|
|
|
|
VkQueueFamilyProperties,
|
|
|
|
queueFamilyCount
|
|
|
|
);
|
|
|
|
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
|
|
|
|
physicalDevice,
|
|
|
|
&queueFamilyCount,
|
|
|
|
queueProps
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < queueFamilyCount; i += 1)
|
|
|
|
{
|
|
|
|
renderer->vkGetPhysicalDeviceSurfaceSupportKHR(
|
|
|
|
physicalDevice,
|
|
|
|
i,
|
|
|
|
surface,
|
|
|
|
&supportsPresent
|
|
|
|
);
|
|
|
|
if ( supportsPresent &&
|
|
|
|
(queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 )
|
|
|
|
{
|
|
|
|
queueFamilyIndices->graphicsFamily = i;
|
|
|
|
queueFamilyIndices->presentFamily = i;
|
|
|
|
foundSuitableDevice = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_stack_free(queueProps);
|
|
|
|
|
|
|
|
if (foundSuitableDevice)
|
|
|
|
{
|
|
|
|
/* We'd really like a discrete GPU, but it's OK either way! */
|
|
|
|
renderer->vkGetPhysicalDeviceProperties(
|
|
|
|
physicalDevice,
|
|
|
|
&deviceProperties
|
|
|
|
);
|
|
|
|
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
|
|
|
{
|
|
|
|
*isIdeal = 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This device is useless for us, next! */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
const char **deviceExtensionNames,
|
|
|
|
uint32_t deviceExtensionCount
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
|
|
|
VkPhysicalDevice *physicalDevices;
|
|
|
|
uint32_t physicalDeviceCount, i, suitableIndex;
|
|
|
|
VkPhysicalDevice physicalDevice;
|
|
|
|
QueueFamilyIndices queueFamilyIndices;
|
|
|
|
uint8_t isIdeal;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
|
|
|
renderer->instance,
|
|
|
|
&physicalDeviceCount,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkEnumeratePhysicalDevices failed: %s",
|
|
|
|
VkErrorMessages(vulkanResult)
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (physicalDeviceCount == 0)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to find any GPUs with Vulkan support");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkEnumeratePhysicalDevices(
|
|
|
|
renderer->instance,
|
|
|
|
&physicalDeviceCount,
|
|
|
|
physicalDevices
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkEnumeratePhysicalDevices failed: %s",
|
|
|
|
VkErrorMessages(vulkanResult)
|
|
|
|
);
|
|
|
|
SDL_stack_free(physicalDevices);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Any suitable device will do, but we'd like the best */
|
|
|
|
suitableIndex = -1;
|
|
|
|
for (i = 0; i < physicalDeviceCount; i += 1)
|
|
|
|
{
|
|
|
|
if (VULKAN_INTERNAL_IsDeviceSuitable(
|
|
|
|
renderer,
|
|
|
|
physicalDevices[i],
|
|
|
|
deviceExtensionNames,
|
|
|
|
deviceExtensionCount,
|
|
|
|
renderer->surface,
|
|
|
|
&queueFamilyIndices,
|
|
|
|
&isIdeal
|
|
|
|
)) {
|
|
|
|
suitableIndex = i;
|
|
|
|
if (isIdeal)
|
|
|
|
{
|
|
|
|
/* This is the one we want! */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (suitableIndex != -1)
|
|
|
|
{
|
|
|
|
physicalDevice = physicalDevices[suitableIndex];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REFRESH_LogError("No suitable physical devices found");
|
|
|
|
SDL_stack_free(physicalDevices);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->physicalDevice = physicalDevice;
|
|
|
|
renderer->queueFamilyIndices = queueFamilyIndices;
|
|
|
|
|
|
|
|
renderer->physicalDeviceDriverProperties.sType =
|
|
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
|
|
|
|
renderer->physicalDeviceDriverProperties.pNext = NULL;
|
|
|
|
|
|
|
|
renderer->physicalDeviceProperties.sType =
|
|
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
|
|
|
renderer->physicalDeviceProperties.pNext =
|
|
|
|
&renderer->physicalDeviceDriverProperties;
|
|
|
|
|
|
|
|
renderer->vkGetPhysicalDeviceProperties2KHR(
|
|
|
|
renderer->physicalDevice,
|
|
|
|
&renderer->physicalDeviceProperties
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free(physicalDevices);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t VULKAN_INTERNAL_CreateLogicalDevice(
|
|
|
|
VulkanRenderer *renderer,
|
|
|
|
const char **deviceExtensionNames,
|
|
|
|
uint32_t deviceExtensionCount
|
|
|
|
) {
|
|
|
|
VkResult vulkanResult;
|
2020-12-17 04:04:47 +00:00
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
VkDeviceCreateInfo deviceCreateInfo;
|
|
|
|
VkPhysicalDeviceFeatures deviceFeatures;
|
|
|
|
|
|
|
|
VkDeviceQueueCreateInfo *queueCreateInfos = SDL_stack_alloc(
|
|
|
|
VkDeviceQueueCreateInfo,
|
|
|
|
2
|
|
|
|
);
|
|
|
|
VkDeviceQueueCreateInfo queueCreateInfoGraphics;
|
|
|
|
VkDeviceQueueCreateInfo queueCreateInfoPresent;
|
|
|
|
|
|
|
|
int32_t queueInfoCount = 1;
|
|
|
|
float queuePriority = 1.0f;
|
|
|
|
|
|
|
|
queueCreateInfoGraphics.sType =
|
|
|
|
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
|
|
queueCreateInfoGraphics.pNext = NULL;
|
|
|
|
queueCreateInfoGraphics.flags = 0;
|
|
|
|
queueCreateInfoGraphics.queueFamilyIndex =
|
|
|
|
renderer->queueFamilyIndices.graphicsFamily;
|
|
|
|
queueCreateInfoGraphics.queueCount = 1;
|
|
|
|
queueCreateInfoGraphics.pQueuePriorities = &queuePriority;
|
|
|
|
|
|
|
|
queueCreateInfos[0] = queueCreateInfoGraphics;
|
|
|
|
|
|
|
|
if (renderer->queueFamilyIndices.presentFamily != renderer->queueFamilyIndices.graphicsFamily)
|
|
|
|
{
|
|
|
|
queueCreateInfoPresent.sType =
|
|
|
|
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
|
|
queueCreateInfoPresent.pNext = NULL;
|
|
|
|
queueCreateInfoPresent.flags = 0;
|
|
|
|
queueCreateInfoPresent.queueFamilyIndex =
|
|
|
|
renderer->queueFamilyIndices.presentFamily;
|
|
|
|
queueCreateInfoPresent.queueCount = 1;
|
|
|
|
queueCreateInfoPresent.pQueuePriorities = &queuePriority;
|
|
|
|
|
|
|
|
queueCreateInfos[1] = queueCreateInfoPresent;
|
|
|
|
queueInfoCount += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* specifying used device features */
|
|
|
|
|
|
|
|
SDL_zero(deviceFeatures);
|
|
|
|
deviceFeatures.occlusionQueryPrecise = VK_TRUE;
|
|
|
|
deviceFeatures.fillModeNonSolid = VK_TRUE;
|
|
|
|
|
|
|
|
/* creating the logical device */
|
|
|
|
|
|
|
|
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
|
|
deviceCreateInfo.pNext = NULL;
|
|
|
|
deviceCreateInfo.flags = 0;
|
|
|
|
deviceCreateInfo.queueCreateInfoCount = queueInfoCount;
|
|
|
|
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos;
|
|
|
|
deviceCreateInfo.enabledLayerCount = 0;
|
|
|
|
deviceCreateInfo.ppEnabledLayerNames = NULL;
|
|
|
|
deviceCreateInfo.enabledExtensionCount = deviceExtensionCount;
|
|
|
|
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;
|
|
|
|
deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDevice(
|
|
|
|
renderer->physicalDevice,
|
|
|
|
&deviceCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->logicalDevice
|
|
|
|
);
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError(
|
|
|
|
"vkCreateDevice failed: %s",
|
|
|
|
VkErrorMessages(vulkanResult)
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load vkDevice entry points */
|
|
|
|
|
|
|
|
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
|
|
|
|
renderer->func = (vkfntype_##func) \
|
|
|
|
renderer->vkGetDeviceProcAddr( \
|
|
|
|
renderer->logicalDevice, \
|
|
|
|
#func \
|
|
|
|
);
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
|
|
|
|
|
|
|
renderer->vkGetDeviceQueue(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->queueFamilyIndices.graphicsFamily,
|
|
|
|
0,
|
|
|
|
&renderer->graphicsQueue
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->vkGetDeviceQueue(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
renderer->queueFamilyIndices.presentFamily,
|
|
|
|
0,
|
|
|
|
&renderer->presentQueue
|
|
|
|
);
|
|
|
|
|
|
|
|
SDL_stack_free(queueCreateInfos);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static REFRESH_Device* VULKAN_CreateDevice(
|
2020-12-22 00:18:21 +00:00
|
|
|
REFRESH_PresentationParameters *presentationParameters,
|
2020-12-17 03:28:02 +00:00
|
|
|
uint8_t debugMode
|
2020-12-17 01:23:49 +00:00
|
|
|
) {
|
|
|
|
REFRESH_Device *result;
|
2020-12-17 03:28:02 +00:00
|
|
|
VulkanRenderer *renderer;
|
2020-12-17 01:23:49 +00:00
|
|
|
|
2020-12-17 04:04:47 +00:00
|
|
|
VkResult vulkanResult;
|
2020-12-18 22:35:33 +00:00
|
|
|
uint32_t i;
|
2020-12-17 04:04:47 +00:00
|
|
|
|
|
|
|
/* Variables: Create fence and semaphores */
|
|
|
|
VkFenceCreateInfo fenceInfo;
|
|
|
|
VkSemaphoreCreateInfo semaphoreInfo;
|
|
|
|
|
|
|
|
/* Variables: Create command pool and command buffer */
|
|
|
|
VkCommandPoolCreateInfo commandPoolCreateInfo;
|
|
|
|
VkCommandBufferAllocateInfo commandBufferAllocateInfo;
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
/* Variables: Shader param layouts */
|
|
|
|
VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo;
|
2020-12-23 04:50:32 +00:00
|
|
|
VkDescriptorSetLayoutBinding emptyVertexSamplerLayoutBinding;
|
|
|
|
VkDescriptorSetLayoutBinding emptyFragmentSamplerLayoutBinding;
|
2020-12-17 19:40:49 +00:00
|
|
|
VkDescriptorSetLayoutBinding vertexParamLayoutBinding;
|
|
|
|
VkDescriptorSetLayoutBinding fragmentParamLayoutBinding;
|
|
|
|
|
2020-12-20 09:29:15 +00:00
|
|
|
/* Variables: UBO Creation */
|
2020-12-23 04:50:32 +00:00
|
|
|
VkDescriptorPoolCreateInfo defaultDescriptorPoolInfo;
|
|
|
|
VkDescriptorPoolSize poolSizes[2];
|
|
|
|
VkDescriptorSetAllocateInfo emptyVertexSamplerDescriptorAllocateInfo;
|
|
|
|
VkDescriptorSetAllocateInfo emptyFragmentSamplerDescriptorAllocateInfo;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
result = (REFRESH_Device*) SDL_malloc(sizeof(REFRESH_Device));
|
|
|
|
ASSIGN_DRIVER(VULKAN)
|
|
|
|
|
2020-12-17 03:28:02 +00:00
|
|
|
renderer = (VulkanRenderer*) SDL_malloc(sizeof(VulkanRenderer));
|
2020-12-22 01:59:08 +00:00
|
|
|
|
|
|
|
/* Load Vulkan entry points */
|
|
|
|
if (SDL_Vulkan_LoadLibrary(NULL) < 0)
|
|
|
|
{
|
|
|
|
REFRESH_LogWarn("Vulkan: SDL_Vulkan_LoadLibrary failed!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
|
|
|
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) SDL_Vulkan_GetVkGetInstanceProcAddr();
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
if (vkGetInstanceProcAddr == NULL)
|
|
|
|
{
|
|
|
|
REFRESH_LogWarn(
|
|
|
|
"SDL_Vulkan_GetVkGetInstanceProcAddr(): %s",
|
|
|
|
SDL_GetError()
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VULKAN_GLOBAL_FUNCTION(name) \
|
|
|
|
name = (PFN_##name) vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \
|
|
|
|
if (name == NULL) \
|
|
|
|
{ \
|
|
|
|
REFRESH_LogWarn("vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
|
|
|
|
2020-12-17 02:12:20 +00:00
|
|
|
result->driverData = (REFRESH_Renderer*) renderer;
|
2020-12-17 03:28:02 +00:00
|
|
|
renderer->debugMode = debugMode;
|
2020-12-22 00:18:21 +00:00
|
|
|
renderer->headless = presentationParameters->deviceWindowHandle == NULL;
|
2020-12-17 03:28:02 +00:00
|
|
|
|
|
|
|
/* Create the VkInstance */
|
2020-12-22 00:18:21 +00:00
|
|
|
if (!VULKAN_INTERNAL_CreateInstance(renderer, presentationParameters->deviceWindowHandle))
|
2020-12-17 03:28:02 +00:00
|
|
|
{
|
|
|
|
REFRESH_LogError("Error creating vulkan instance");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-22 00:18:21 +00:00
|
|
|
renderer->deviceWindowHandle = presentationParameters->deviceWindowHandle;
|
|
|
|
renderer->presentMode = presentationParameters->presentMode;
|
2020-12-17 03:28:02 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create the WSI vkSurface
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!SDL_Vulkan_CreateSurface(
|
2020-12-22 00:18:21 +00:00
|
|
|
(SDL_Window*) renderer->deviceWindowHandle,
|
2020-12-17 03:28:02 +00:00
|
|
|
renderer->instance,
|
|
|
|
&renderer->surface
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError(
|
|
|
|
"SDL_Vulkan_CreateSurface failed: %s",
|
|
|
|
SDL_GetError()
|
|
|
|
);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get vkInstance entry points
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
|
|
|
renderer->func = (vkfntype_##func) vkGetInstanceProcAddr(renderer->instance, #func);
|
|
|
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Choose/Create vkDevice
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (SDL_strcmp(SDL_GetPlatform(), "Stadia") != 0)
|
|
|
|
{
|
|
|
|
deviceExtensionCount -= 1;
|
|
|
|
}
|
|
|
|
if (!VULKAN_INTERNAL_DeterminePhysicalDevice(
|
|
|
|
renderer,
|
|
|
|
deviceExtensionNames,
|
|
|
|
deviceExtensionCount
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to determine a suitable physical device");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
REFRESH_LogInfo("Refresh Driver: Vulkan");
|
|
|
|
REFRESH_LogInfo(
|
|
|
|
"Vulkan Device: %s",
|
|
|
|
renderer->physicalDeviceProperties.properties.deviceName
|
|
|
|
);
|
|
|
|
REFRESH_LogInfo(
|
|
|
|
"Vulkan Driver: %s %s",
|
|
|
|
renderer->physicalDeviceDriverProperties.driverName,
|
|
|
|
renderer->physicalDeviceDriverProperties.driverInfo
|
|
|
|
);
|
|
|
|
REFRESH_LogInfo(
|
|
|
|
"Vulkan Conformance: %u.%u.%u",
|
|
|
|
renderer->physicalDeviceDriverProperties.conformanceVersion.major,
|
|
|
|
renderer->physicalDeviceDriverProperties.conformanceVersion.minor,
|
|
|
|
renderer->physicalDeviceDriverProperties.conformanceVersion.patch
|
|
|
|
);
|
|
|
|
REFRESH_LogWarn(
|
2020-12-22 01:59:08 +00:00
|
|
|
"\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
2020-12-17 03:28:02 +00:00
|
|
|
"! Refresh Vulkan is still in development! !\n"
|
|
|
|
"! The API is unstable and subject to change! !\n"
|
|
|
|
"! You have been warned! !\n"
|
|
|
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateLogicalDevice(
|
|
|
|
renderer,
|
|
|
|
deviceExtensionNames,
|
|
|
|
deviceExtensionCount
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create logical device");
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-12-17 01:23:49 +00:00
|
|
|
|
2020-12-17 03:50:31 +00:00
|
|
|
/*
|
|
|
|
* Create initial swapchain
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!renderer->headless)
|
|
|
|
{
|
|
|
|
if (VULKAN_INTERNAL_CreateSwapchain(renderer) != CREATE_SWAPCHAIN_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to create swap chain");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->needNewSwapChain = 0;
|
|
|
|
renderer->shouldPresent = 0;
|
|
|
|
renderer->swapChainImageAcquired = 0;
|
|
|
|
|
2020-12-17 04:04:47 +00:00
|
|
|
/*
|
|
|
|
* Create fence and semaphores
|
|
|
|
*/
|
|
|
|
|
|
|
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
|
|
|
fenceInfo.pNext = NULL;
|
|
|
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
|
|
|
|
|
|
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
|
|
|
semaphoreInfo.pNext = NULL;
|
|
|
|
semaphoreInfo.flags = 0;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateSemaphore(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&semaphoreInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->imageAvailableSemaphore
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateFence", vulkanResult);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateSemaphore(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&semaphoreInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->renderFinishedSemaphore
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateSemaphore", vulkanResult);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateFence(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&fenceInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->inFlightFence
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateSemaphore", vulkanResult);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-22 01:59:08 +00:00
|
|
|
/* Threading */
|
|
|
|
|
|
|
|
renderer->allocatorLock = SDL_CreateMutex();
|
|
|
|
renderer->commandLock = SDL_CreateMutex();
|
|
|
|
|
2020-12-17 04:04:47 +00:00
|
|
|
/*
|
|
|
|
* Create command pool and buffers
|
|
|
|
*/
|
|
|
|
|
|
|
|
commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
|
|
commandPoolCreateInfo.pNext = NULL;
|
|
|
|
commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
|
|
|
commandPoolCreateInfo.queueFamilyIndex = renderer->queueFamilyIndices.graphicsFamily;
|
|
|
|
vulkanResult = renderer->vkCreateCommandPool(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&commandPoolCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->commandPool
|
|
|
|
);
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkCreateCommandPool", vulkanResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->allocatedCommandBufferCount = 4;
|
|
|
|
renderer->inactiveCommandBuffers = SDL_malloc(sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount);
|
|
|
|
renderer->activeCommandBuffers = SDL_malloc(sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount);
|
|
|
|
renderer->submittedCommandBuffers = SDL_malloc(sizeof(VkCommandBuffer) * renderer->allocatedCommandBufferCount);
|
|
|
|
renderer->inactiveCommandBufferCount = renderer->allocatedCommandBufferCount;
|
|
|
|
renderer->activeCommandBufferCount = 0;
|
|
|
|
renderer->submittedCommandBufferCount = 0;
|
|
|
|
|
|
|
|
commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
|
|
commandBufferAllocateInfo.pNext = NULL;
|
|
|
|
commandBufferAllocateInfo.commandPool = renderer->commandPool;
|
|
|
|
commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
|
|
commandBufferAllocateInfo.commandBufferCount = renderer->allocatedCommandBufferCount;
|
|
|
|
vulkanResult = renderer->vkAllocateCommandBuffers(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&commandBufferAllocateInfo,
|
|
|
|
renderer->inactiveCommandBuffers
|
|
|
|
);
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
LogVulkanResult("vkAllocateCommandBuffers", vulkanResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->currentCommandCount = 0;
|
|
|
|
|
|
|
|
VULKAN_INTERNAL_BeginCommandBuffer(renderer);
|
|
|
|
|
2020-12-22 01:59:08 +00:00
|
|
|
/* Memory Allocator */
|
|
|
|
|
|
|
|
renderer->memoryAllocator = (VulkanMemoryAllocator*) SDL_malloc(
|
|
|
|
sizeof(VulkanMemoryAllocator)
|
|
|
|
);
|
|
|
|
|
|
|
|
for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1)
|
|
|
|
{
|
|
|
|
renderer->memoryAllocator->subAllocators[i].nextAllocationSize = STARTING_ALLOCATION_SIZE;
|
|
|
|
renderer->memoryAllocator->subAllocators[i].allocations = NULL;
|
|
|
|
renderer->memoryAllocator->subAllocators[i].allocationCount = 0;
|
|
|
|
renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc(
|
|
|
|
sizeof(VulkanMemoryFreeRegion*) * 4
|
|
|
|
);
|
|
|
|
renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCount = 0;
|
|
|
|
renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCapacity = 4;
|
|
|
|
}
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
/* UBO Data */
|
|
|
|
|
|
|
|
renderer->vertexUBO = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
renderer,
|
|
|
|
UBO_ACTUAL_SIZE,
|
|
|
|
RESOURCE_ACCESS_VERTEX_SHADER_READ_UNIFORM_BUFFER,
|
|
|
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
|
|
SUB_BUFFER_COUNT,
|
|
|
|
renderer->vertexUBO
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create vertex UBO!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->fragmentUBO = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
renderer,
|
|
|
|
UBO_ACTUAL_SIZE,
|
|
|
|
RESOURCE_ACCESS_FRAGMENT_SHADER_READ_UNIFORM_BUFFER,
|
|
|
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
|
|
|
SUB_BUFFER_COUNT,
|
|
|
|
renderer->fragmentUBO
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create fragment UBO!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer->minUBOAlignment = renderer->physicalDeviceProperties.properties.limits.minUniformBufferOffsetAlignment;
|
|
|
|
renderer->vertexUBOOffset = 0;
|
|
|
|
renderer->vertexUBOBlockIncrement = 0;
|
|
|
|
renderer->fragmentUBOOffset = 0;
|
|
|
|
renderer->fragmentUBOBlockIncrement = 0;
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
/* Set up UBO layouts */
|
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
emptyVertexSamplerLayoutBinding.binding = 0;
|
|
|
|
emptyVertexSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
emptyVertexSamplerLayoutBinding.descriptorCount = 0;
|
|
|
|
emptyVertexSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
emptyVertexSamplerLayoutBinding.pImmutableSamplers = NULL;
|
|
|
|
|
|
|
|
setLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
|
|
setLayoutCreateInfo.pNext = NULL;
|
|
|
|
setLayoutCreateInfo.flags = 0;
|
|
|
|
setLayoutCreateInfo.bindingCount = 1;
|
|
|
|
setLayoutCreateInfo.pBindings = &emptyVertexSamplerLayoutBinding;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->emptyVertexSamplerLayout
|
|
|
|
);
|
|
|
|
|
|
|
|
emptyFragmentSamplerLayoutBinding.binding = 0;
|
|
|
|
emptyFragmentSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
emptyFragmentSamplerLayoutBinding.descriptorCount = 0;
|
|
|
|
emptyFragmentSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
emptyFragmentSamplerLayoutBinding.pImmutableSamplers = NULL;
|
|
|
|
|
|
|
|
setLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
|
|
setLayoutCreateInfo.pNext = NULL;
|
|
|
|
setLayoutCreateInfo.flags = 0;
|
|
|
|
setLayoutCreateInfo.bindingCount = 1;
|
|
|
|
setLayoutCreateInfo.pBindings = &emptyFragmentSamplerLayoutBinding;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->emptyFragmentSamplerLayout
|
|
|
|
);
|
|
|
|
|
2020-12-17 19:40:49 +00:00
|
|
|
vertexParamLayoutBinding.binding = 0;
|
|
|
|
vertexParamLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
|
|
|
vertexParamLayoutBinding.descriptorCount = 1;
|
|
|
|
vertexParamLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
vertexParamLayoutBinding.pImmutableSamplers = NULL;
|
|
|
|
|
|
|
|
setLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
|
|
setLayoutCreateInfo.pNext = NULL;
|
|
|
|
setLayoutCreateInfo.flags = 0;
|
|
|
|
setLayoutCreateInfo.bindingCount = 1;
|
|
|
|
setLayoutCreateInfo.pBindings = &vertexParamLayoutBinding;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->vertexParamLayout
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to create vertex UBO layout!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fragmentParamLayoutBinding.binding = 0;
|
|
|
|
fragmentParamLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
|
|
|
fragmentParamLayoutBinding.descriptorCount = 1;
|
|
|
|
fragmentParamLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
fragmentParamLayoutBinding.pImmutableSamplers = NULL;
|
|
|
|
|
|
|
|
setLayoutCreateInfo.bindingCount = 1;
|
|
|
|
setLayoutCreateInfo.pBindings = &fragmentParamLayoutBinding;
|
|
|
|
|
|
|
|
vulkanResult = renderer->vkCreateDescriptorSetLayout(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&setLayoutCreateInfo,
|
|
|
|
NULL,
|
|
|
|
&renderer->fragmentParamLayout
|
|
|
|
);
|
|
|
|
|
|
|
|
if (vulkanResult != VK_SUCCESS)
|
|
|
|
{
|
|
|
|
REFRESH_LogError("Failed to create fragment UBO layout!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
/* Default Descriptors */
|
2020-12-20 09:29:15 +00:00
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
/* default empty sampler descriptor sets */
|
2020-12-23 04:50:32 +00:00
|
|
|
poolSizes[0].descriptorCount = 2;
|
|
|
|
poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
|
|
|
2020-12-23 21:11:09 +00:00
|
|
|
/* UBO descriptor sets */
|
|
|
|
poolSizes[1].descriptorCount = UBO_POOL_SIZE;
|
2020-12-23 04:50:32 +00:00
|
|
|
poolSizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
2020-12-23 04:50:32 +00:00
|
|
|
defaultDescriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
|
|
defaultDescriptorPoolInfo.pNext = NULL;
|
|
|
|
defaultDescriptorPoolInfo.flags = 0;
|
2020-12-23 21:11:09 +00:00
|
|
|
defaultDescriptorPoolInfo.maxSets = UBO_POOL_SIZE + 2;
|
2020-12-23 04:50:32 +00:00
|
|
|
defaultDescriptorPoolInfo.poolSizeCount = 2;
|
|
|
|
defaultDescriptorPoolInfo.pPoolSizes = poolSizes;
|
2020-12-20 09:29:15 +00:00
|
|
|
|
|
|
|
renderer->vkCreateDescriptorPool(
|
|
|
|
renderer->logicalDevice,
|
2020-12-23 04:50:32 +00:00
|
|
|
&defaultDescriptorPoolInfo,
|
2020-12-20 09:29:15 +00:00
|
|
|
NULL,
|
2020-12-23 04:50:32 +00:00
|
|
|
&renderer->defaultDescriptorPool
|
|
|
|
);
|
|
|
|
|
|
|
|
emptyVertexSamplerDescriptorAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
emptyVertexSamplerDescriptorAllocateInfo.pNext = NULL;
|
|
|
|
emptyVertexSamplerDescriptorAllocateInfo.descriptorPool = renderer->defaultDescriptorPool;
|
|
|
|
emptyVertexSamplerDescriptorAllocateInfo.descriptorSetCount = 1;
|
|
|
|
emptyVertexSamplerDescriptorAllocateInfo.pSetLayouts = &renderer->emptyVertexSamplerLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&emptyVertexSamplerDescriptorAllocateInfo,
|
|
|
|
&renderer->emptyVertexSamplerDescriptorSet
|
|
|
|
);
|
|
|
|
|
|
|
|
emptyFragmentSamplerDescriptorAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
|
|
emptyFragmentSamplerDescriptorAllocateInfo.pNext = NULL;
|
|
|
|
emptyFragmentSamplerDescriptorAllocateInfo.descriptorPool = renderer->defaultDescriptorPool;
|
|
|
|
emptyFragmentSamplerDescriptorAllocateInfo.descriptorSetCount = 1;
|
|
|
|
emptyFragmentSamplerDescriptorAllocateInfo.pSetLayouts = &renderer->emptyFragmentSamplerLayout;
|
|
|
|
|
|
|
|
renderer->vkAllocateDescriptorSets(
|
|
|
|
renderer->logicalDevice,
|
|
|
|
&emptyFragmentSamplerDescriptorAllocateInfo,
|
|
|
|
&renderer->emptyFragmentSamplerDescriptorSet
|
2020-12-20 09:29:15 +00:00
|
|
|
);
|
|
|
|
|
2020-12-21 23:44:43 +00:00
|
|
|
/* Initialize buffer space */
|
|
|
|
|
|
|
|
renderer->buffersInUseCapacity = 32;
|
2020-12-22 01:59:08 +00:00
|
|
|
renderer->buffersInUseCount = 0;
|
2020-12-21 23:44:43 +00:00
|
|
|
renderer->buffersInUse = (VulkanBuffer**)SDL_malloc(
|
|
|
|
sizeof(VulkanBuffer*) * renderer->buffersInUseCapacity
|
|
|
|
);
|
|
|
|
|
|
|
|
renderer->submittedBufferCapacity = 32;
|
|
|
|
renderer->submittedBufferCount = 0;
|
|
|
|
renderer->submittedBuffers = (VulkanBuffer**)SDL_malloc(
|
|
|
|
sizeof(VulkanBuffer*) * renderer->submittedBufferCapacity
|
|
|
|
);
|
|
|
|
|
2020-12-19 01:03:26 +00:00
|
|
|
/* Staging Buffer */
|
|
|
|
|
|
|
|
renderer->textureStagingBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
|
|
|
|
|
|
|
|
if (!VULKAN_INTERNAL_CreateBuffer(
|
|
|
|
renderer,
|
|
|
|
TEXTURE_STAGING_SIZE,
|
|
|
|
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
|
|
|
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
2020-12-19 04:08:07 +00:00
|
|
|
1,
|
2020-12-19 01:03:26 +00:00
|
|
|
renderer->textureStagingBuffer
|
|
|
|
)) {
|
|
|
|
REFRESH_LogError("Failed to create texture staging buffer!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-19 05:35:21 +00:00
|
|
|
/* Descriptor Pools */
|
|
|
|
|
|
|
|
renderer->descriptorPools = NULL;
|
|
|
|
renderer->descriptorPoolCount = 0;
|
|
|
|
|
2020-12-17 01:23:49 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-12-17 00:27:14 +00:00
|
|
|
REFRESH_Driver VulkanDriver = {
|
|
|
|
"Vulkan",
|
|
|
|
VULKAN_CreateDevice
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif //REFRESH_DRIVER_VULKAN
|