Files

6762 lines
222 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "dl_vk.h"
#ifndef DL_DISABLE_RENDER
#include <set>
#include <ktx.h>
#include <ktxvulkan.h>
#include "system/dl_system.h"
#include "system/dl_android.h"
#include "math/dl_mesh.h"
#include "system/dl_engine.h"
#include "system/dl_time.h"
namespace dl
{
VK* g_vk = nullptr;
constexpr uint32_t BINDING_INDEX_UBO = 0;
constexpr uint32_t BINDING_INDEX_MATERIAL = 1;
constexpr uint32_t BINDING_INDEX_PASS = 2;
constexpr uint32_t BINDING_INDEX_CASCADE = 3; // 阴影管线里是 0
constexpr uint32_t BINDING_INDEX_IBL = 4;
constexpr uint32_t BINDING_INDEX_BRDF = 5;
constexpr uint32_t BINDING_INDEX_SHADOW = 6;
constexpr size_t CANVAS_ID_RENDER_TARGET_MAX = 16;
void VK::_init(GLFWwindow* window)
{
_curPushConstant = 0;
//
_camera = &_cameraDefault;
//
_check_extension();
_check_layer();
_create_instance();
_create_debug_messenger();
_create_surface(window);
//创建物理设备前,需要先创建surface
_create_physical_device();
_create_logical_device();
_create_swap_chain(window);
_create_image_view();
_create_render_pass();
_create_descriptor_set_layout(); // 0
_create_descriptor_set_layout_texture(); // 1
_create_descriptor_set_layout_bone(); // 2
_create_pipeline_layout_3d();
_create_pipeline_layout_bone();
_create_command_pool();
_create_command_upload();
_create_color_resources();
_create_depth_resources();
_create_frame_buffer();
_create_texture_sampler();
_create_uniform_buffers();
_create_uniform_bone();
_create_descriptor_pool();
_create_descriptor_sets();
_create_ibl();
_create_command_buffer();
_create_sync_objects();
//创建默认3d管线贴图
Image* image = Img::Create({ 32, 32 }, ColorDef::WHITE);
size_t id = CreateTextureReal(image, true, true);
assert(id == 0);
_mapPath2Texture[""] = 0;
//默认材质
ModelMaterial m;
m._materialName = "default";
Fill::Value(m._material._baseColorFactor, 1.0f);
Fill::Value(m._material._emissiveFactor, 0.0f);
m._material._baseColorTextureSet = -1;
m._material._physicalDescriptorTextureSet = -1;
m._material._normalTextureSet = -1;
m._material._occlusionTextureSet = -1;
m._material._emissiveTextureSet = -1;
m._material._metallicFactor = 0.0f;
m._material._roughnessFactor = 0.5f;
m._material._alphaMask = 0.0f;
m._material._alphaMaskCutoff = 0.0f;
m._material._emissiveStrength = 0.0f;
size_t id_mat = CreatePrimitive(m);
assert(id_mat == 0);
_create_2d();
_create_gfx();
_create_skybox();
_create_shadow();
_create_pipeline_all();
size_t i = CreateRenderTarget();
assert(i == 0);
}
void VK::_check_extension()
{
LogLimit l;
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
if (extensionCount == 0)
{
log_err0("extensionCount 为0!");
return;
}
else
log_msg("{} extensions supported", extensionCount);
_allExtension.resize(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, _allExtension.data());
log("available extensions:");
for (auto& iter : _allExtension)
{
log(iter.extensionName);
}
}
void VK::_create_instance()
{
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Hello Triangle";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
auto extensions = _get_required_extensions();
#if DL_PLATFORM == DL_PLATFORM_APPLE
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif
createInfo.enabledExtensionCount = (uint32_t)extensions.size();
createInfo.ppEnabledExtensionNames = extensions.data();
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
if (ENABLE_VALIDATION_LAYERS)
{
createInfo.enabledLayerCount = static_cast<uint32_t>(_allValidationLayer.size());
createInfo.ppEnabledLayerNames = _allValidationLayer.data();
PopulateDebugMessengerCreateInfo(debugCreateInfo);
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
}
else
{
createInfo.enabledLayerCount = 0;
createInfo.pNext = nullptr;
}
if (vkCreateInstance(&createInfo, nullptr, &_instance) != VK_SUCCESS)
{
log_err0("vkCreateInstance 失败!Debug模式请安装VulkanSDK。");
}
}
void VK::_check_layer()
{
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
_allLayer.resize(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, _allLayer.data());
//打印所有layer
LogLimit l;
log("available layers:");
for (auto& iter : _allLayer)
{
log(iter.layerName);
}
}
bool VK::_check_validation_layer()
{
//检查layer支持,不支持直接错误
bool support = true;
for (const char* layerName : _allValidationLayer)
{
bool layerFound = false;
for (const auto& layerProperties : _allLayer)
{
if (strcmp(layerName, layerProperties.layerName) == 0)
{
layerFound = true;
break;
}
}
if (!layerFound)
{
support = false;
break;
}
}
//验证层开启 且不支持
if (ENABLE_VALIDATION_LAYERS && !support)
{
log_err0("验证层不支持!");
return false;
}
return ENABLE_VALIDATION_LAYERS;
}
void VK::_create_physical_device()
{
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr);
if (deviceCount == 0)
{
log_err0("没有物理设备支持!");
return;
}
_allPhysicalDevice.resize(deviceCount);
vkEnumeratePhysicalDevices(_instance, &deviceCount, _allPhysicalDevice.data());
//获得支持特性的设备
_physicalDevice = VK_NULL_HANDLE;
for (auto& iter : _allPhysicalDevice)
{
if (_is_device_suitable(iter))
{
_physicalDevice = iter;
_param._msaaLevel = GetMaxUsableSampleCount();
break;
}
}
if (_physicalDevice == VK_NULL_HANDLE)
{
log_err0("没有物理设备支持所要求的特性!");
return;
}
std::string str_gpu;
VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(_physicalDevice, &properties);
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(_physicalDevice, &memoryProperties);
str_gpu += fmt::format("{}\n", properties.deviceName);
for (size_t i = 0; i < memoryProperties.memoryHeapCount; ++i)
{
if(memoryProperties.memoryHeaps[i].flags != VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
continue;
double k = 1024 * 1024 * 1024;
str_gpu += fmt::format("显存:{:.2f}GB\n", memoryProperties.memoryHeaps[i].size / k);
}
str_gpu.pop_back();
log_msg0(str_gpu);
}
bool VK::_is_device_suitable(VkPhysicalDevice device)
{
// 队列族
uint32_t qf_index;
if (!_find_queue_families(device, qf_index))
return false;
//扩展
bool extensionsSupported = _check_device_extension(device);
//交换链
bool swapChainAdequate = false;
if (extensionsSupported)
{
SwapChainSupportDetails swapChainSupport = _query_swap_chain_support(device);
swapChainAdequate = !swapChainSupport._formats.empty() && !swapChainSupport._presentModes.empty();
}
VkPhysicalDeviceFeatures supportedFeatures;
vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(device, &properties);
uint32_t cb_size = properties.limits.maxPushConstantsSize;
if (OPEN_FILL_MODE_NON_SOLID && !supportedFeatures.fillModeNonSolid)
return false;// 非填充模式支持(安卓有的不支持)
return extensionsSupported
&& swapChainAdequate
&& supportedFeatures.samplerAnisotropy;
}
bool VK::_find_queue_families(VkPhysicalDevice device, uint32_t& index, int type)
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
// 至少一个支持 VK_QUEUE_GRAPHICS_BIT
// VK_QUEUE_GRAPHICS_BIT 默认带有 VK_QUEUE_TRANSFER_BIT
int i = 0;
for (const auto& queueFamily : queueFamilies)
{
if (type == 0)
{
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, _surface, &presentSupport);
if (presentSupport)
{
index = i;
return true;
}
}
}
else if (type == 1)
{
if (!(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
&& !(queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)
&& (queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT))
{
index = i;
return true;
}
}
else
return false;
++i;
}
if (type == 1)
{// 退行到默认
return _find_queue_families(device, index, 0);
}
return false;
}
void VK::_create_logical_device()
{
// 队列族
uint32_t qf_index0;
uint32_t qf_index1;
if (!_find_queue_families(_physicalDevice, qf_index0)
|| !_find_queue_families(_physicalDevice, qf_index1, 1))
{
log_damage("设备没有合适的队列族!");
return;
}
log_msg("使用队列族:{}, {}", qf_index0, qf_index1);
// 物理设备特性
VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.samplerAnisotropy = VK_TRUE;
if (OPEN_SAMPLE_SHADING)
deviceFeatures.sampleRateShading = VK_TRUE;
if (OPEN_FILL_MODE_NON_SOLID)
deviceFeatures.fillModeNonSolid = VK_TRUE;
VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pEnabledFeatures = &deviceFeatures;
// 设备扩展
createInfo.enabledExtensionCount = static_cast<uint32_t>(_allDeviceExtension.size());
createInfo.ppEnabledExtensionNames = _allDeviceExtension.data();
// 验证层
if (_check_validation_layer())
{
createInfo.enabledLayerCount = static_cast<uint32_t>(_allValidationLayer.size());
createInfo.ppEnabledLayerNames = _allValidationLayer.data();
}
else
{
createInfo.enabledLayerCount = 0;
}
// 创建呈现队列
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = {
qf_index0, qf_index1
};
float queuePriority1 = 1.0f;
for (uint32_t queueFamily : uniqueQueueFamilies)
{
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority1;
queueCreateInfos.push_back(queueCreateInfo);
}
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data();
if (vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS)
{
log_err0("创建逻辑设备失败!");
}
//从device获得图形队列
vkGetDeviceQueue(_device, qf_index0, 0, &_graphicsQueue);
//从device获得呈现队列
vkGetDeviceQueue(_device, qf_index0, 0, &_presentQueue);
//从device获得传输队列
vkGetDeviceQueue(_device, qf_index1, 0, &_transferQueue);
}
bool VK::_check_device_extension(VkPhysicalDevice device)
{
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
std::set<std::string> requiredExtensions(_allDeviceExtension.begin(), _allDeviceExtension.end());
for (const auto& extension : availableExtensions) {
requiredExtensions.erase(extension.extensionName);
}
return requiredExtensions.empty();
}
void VK::_create_surface(GLFWwindow* window)
{
#if (DL_PLATFORM == DL_PLATFORM_ANDROID)
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo{};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
// 创建新的窗口用于视频显示
// ANativeWindow*& native_window = g_android->_app->window;
// native_window = ANativeWindow_fromSurface(
// g_android->_app->activity->env, g_android->_surface);
// 设置窗口属性
// ANativeWindow_setBuffersGeometry(native_window, 1080, 2340, WINDOW_FORMAT_RGBA_8888);
surfaceCreateInfo.window = g_android->_app->window;
if(vkCreateAndroidSurfaceKHR(_instance, &surfaceCreateInfo, nullptr, &_surface) != VK_SUCCESS)
{
log_err0("创建窗口表面失败!");
}
g_android->_surfaceState = 2;
#else
if (glfwCreateWindowSurface(_instance, window, nullptr, &_surface) != VK_SUCCESS)
{
log_err0("创建窗口表面失败!");
}
#endif
// 安卓模拟器返回真,但有_surface为空的情况(应该是代码没有等待的问题,已经修正)
assert(_surface);
}
void VK::_create_swap_chain(GLFWwindow* window)
{
SwapChainSupportDetails swapChainSupport = _query_swap_chain_support(_physicalDevice);
VkSurfaceFormatKHR surfaceFormat = _choose_swap_surface_format(swapChainSupport._formats);
VkPresentModeKHR presentMode = _choose_swap_present_mode(swapChainSupport._presentModes);
VkExtent2D extent = _choose_swap_extent(swapChainSupport._capabilities, window);
uint32_t imageCount = swapChainSupport._capabilities.minImageCount + 1;
if (swapChainSupport._capabilities.maxImageCount > 0
&& imageCount > swapChainSupport._capabilities.maxImageCount)
{
imageCount = swapChainSupport._capabilities.maxImageCount;
}
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = _surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
// 截图必须依赖 VK_IMAGE_USAGE_TRANSFER_SRC_BIT
/*QueueFamilyIndices indices = _find_queue_families(_physicalDevice);
uint32_t queueFamilyIndices[] = { indices._graphicsFamily.value(), indices._presentFamily.value() };*/
// 队列族
uint32_t qf_index;
if (!_find_queue_families(_physicalDevice, qf_index))
{
log_damage("设备没有合适的队列族!");
return;
}
/*if (indices._graphicsFamily != indices._presentFamily) {
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else */ {
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0; // Optional
createInfo.pQueueFamilyIndices = nullptr; // Optional
}
VkSurfaceTransformFlagBitsKHR preTransform;
if (swapChainSupport._capabilities.supportedTransforms &
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
{
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
}
else
{
preTransform = swapChainSupport._capabilities.currentTransform;
}
createInfo.preTransform = preTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(_device, &createInfo, nullptr, &_swapChain) != VK_SUCCESS)
{
log_err0("创建交换链失败!");
return;
}
//获取交换链图像
vkGetSwapchainImagesKHR(_device, _swapChain, &imageCount, nullptr);
_allImageSwapChain.resize(imageCount);
vkGetSwapchainImagesKHR(_device, _swapChain, &imageCount, _allImageSwapChain.data());
_formatSwapChainImage = surfaceFormat.format;
_extentSwapChain = extent;
_countFrame = imageCount;
}
SwapChainSupportDetails VK::_query_swap_chain_support(VkPhysicalDevice device)
{
SwapChainSupportDetails details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, _surface, &details._capabilities);
//返回表面支持格式
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, _surface, &formatCount, nullptr);
if (formatCount != 0)
{
details._formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, _surface, &formatCount, details._formats.data());
}
//返回表面支持的呈现模式
uint32_t presentModeCount = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, _surface, &presentModeCount, nullptr);
// 安卓模拟器不会返回有效值
assert(presentModeCount < 1024);
if (presentModeCount != 0)
{
details._presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, _surface, &presentModeCount, details._presentModes.data());
}
return details;
}
VkSurfaceFormatKHR VK::_choose_swap_surface_format(const std::vector<VkSurfaceFormatKHR>& availableFormats)
{
if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED)
{
return { DL_VK_FORMAT_SURFACE, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
}
for (const auto& availableFormat : availableFormats)
{
if (availableFormat.format == DL_VK_FORMAT_SURFACE
&& availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
return availableFormat;
}
}
log_err0("未找到合适的交换链格式!");
return availableFormats[0];//直接简单的返回第一个
}
VkPresentModeKHR VK::_choose_swap_present_mode(const std::vector<VkPresentModeKHR>& availablePresentModes)
{
// 优先三重缓冲
for (const auto& availablePresentMode : availablePresentModes)
{
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
return availablePresentMode;
}
//
for (const auto& availablePresentMode : availablePresentModes)
{
if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR)
return availablePresentMode;
}
return VK_PRESENT_MODE_FIFO_KHR; // 必定支持的模式(A卡会开启垂直同步)
}
VkExtent2D VK::_choose_swap_extent(const VkSurfaceCapabilitiesKHR& capabilities,
GLFWwindow* window)
{
if (capabilities.currentExtent.width != (std::numeric_limits<uint32_t>::max)())
{
return capabilities.currentExtent;
}
else
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
VkExtent2D actualExtent =
{
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
};
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
return actualExtent;
}
}
void VK::_create_image_view()
{
_allImageViewSwapChain.resize(_allImageSwapChain.size());
for (size_t i = 0; i < _allImageSwapChain.size(); ++i)
{
_allImageViewSwapChain[i] = CreateImageView(_allImageSwapChain[i],
_formatSwapChainImage, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
}
VkShaderModule VK::CreateShaderModule(Buffer& buf)
{
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = buf.size();
createInfo.pCode = (const uint32_t*)buf.data();
VkShaderModule shaderModule;
if (vkCreateShaderModule(_device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
{
// 可能是没有拷贝 dl/res/dl 文件夹到资源目录,或是未设置工作路径
log_damage0("创建shader模块失败!");
return {};
}
return shaderModule;
}
void VK::_create_render_pass()
{
// 3d
{
// color
VkAttachmentDescription colorAttachment{};
colorAttachment.format = _formatSwapChainImage;
colorAttachment.samples = _param._msaaLevel;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// depth
VkAttachmentDescription depthAttachment{};
depthAttachment.format = FindDepthFormat();
depthAttachment.samples = _param._msaaLevel;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
// color resolve
VkAttachmentDescription colorAttachmentResolve{};
colorAttachmentResolve.format = _formatSwapChainImage;
colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // 保留给shader使用
colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference colorAttachmentResolveRef{};
colorAttachmentResolveRef.attachment = 2;
colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
subpass.pResolveAttachments = &colorAttachmentResolveRef;
// 子流程依赖
VkSubpassDependency dependency{};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcAccessMask = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
| VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
| VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
// 渲染流程
std::array<VkAttachmentDescription, 3> attachments = {
colorAttachment, depthAttachment, colorAttachmentResolve };
VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
if (vkCreateRenderPass(_device, &renderPassInfo, nullptr, &_renderPass3D) != VK_SUCCESS)
{
log_damage0("创建渲染流程3d失败!");
return;
}
}
// 2d
{
// color
VkAttachmentDescription colorAttachment{};
colorAttachment.format = _formatSwapChainImage;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// depth
VkAttachmentDescription depthAttachment{};
depthAttachment.format = FindDepthFormat();
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
subpass.pResolveAttachments = nullptr;
// 渲染流程
std::array<VkAttachmentDescription, 2> attachments = {
colorAttachment, depthAttachment };
VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = (uint32_t)attachments.size();
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 0;
renderPassInfo.pDependencies = nullptr;
if (vkCreateRenderPass(_device, &renderPassInfo, nullptr, &_renderPass2D) != VK_SUCCESS)
{
log_damage0("创建渲染流程2d失败!");
return;
}
}
}
void VK::_create_pipeline_layout_3d()
{
// 推送常量区
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(PushConstantData);
// 管线布局
std::array<VkDescriptorSetLayout, 3> dsp_set_layout = {
_descriptorSetLayout,
_descriptorSetLayoutTex,
_descriptorSetLayoutBone
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = (uint32_t)dsp_set_layout.size(); // Optional
pipelineLayoutInfo.pSetLayouts = dsp_set_layout.data(); // Optional
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS)
{
log_damage0("创建管线布局失败!");
return;
}
}
void VK::_create_pipeline_layout_skybox()
{
// 管线布局
std::array<VkDescriptorSetLayout, 1> dsp_set_layout = {
_skybox._descriptorSetLayout
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = (uint32_t)dsp_set_layout.size(); // Optional
pipelineLayoutInfo.pSetLayouts = dsp_set_layout.data(); // Optional
pipelineLayoutInfo.pushConstantRangeCount = 0;
pipelineLayoutInfo.pPushConstantRanges = nullptr;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_skybox._pipelineLayout) != VK_SUCCESS)
{
log_damage0("创建管线布局(skybox)失败!");
return;
}
}
void VK::_create_render_pass_shadow()
{
// depth
VkAttachmentDescription depthAttachment{};
depthAttachment.format = FORMAT_SHADOW_IMAGE;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // 需要保持
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
VkAttachmentReference depthAttachmentRef{};
depthAttachmentRef.attachment = 0;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//
VkSubpassDescription subpass{};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 0;
subpass.pColorAttachments = nullptr;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
subpass.pResolveAttachments = nullptr;
// 子流程依赖
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// 渲染流程
std::array<VkAttachmentDescription, 1> attachments = { depthAttachment };
VkRenderPassCreateInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = (uint32_t)attachments.size();
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = (uint32_t)dependencies.size();
renderPassInfo.pDependencies = dependencies.data();
if (vkCreateRenderPass(_device, &renderPassInfo, nullptr, &_shadow._renderPass) != VK_SUCCESS)
{
log_damage0("渲染流程(shadow)创建失败!");
return;
}
}
VkPipelineLayout VK::_create_pipline_layout_shadow()
{
VkPipelineLayout ret = VK_NULL_HANDLE;
// 推送常量区
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(PushConstantCSM);
// 管线布局
std::array<VkDescriptorSetLayout, 3> dsp_set_layout = {
_shadow._descriptorSetLayout, _descriptorSetLayoutTex, _descriptorSetLayoutBone
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = (uint32_t)dsp_set_layout.size(); // Optional
pipelineLayoutInfo.pSetLayouts = dsp_set_layout.data(); // Optional
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &ret) != VK_SUCCESS)
{
log_damage0("创建管线布局(shadow)失败!");
return ret;
}
return ret;
}
VkPipeline VK::_create_graphics_pipeline_shadow(std::string_view vs, std::string_view ps,
VkVertexInputBindingDescription* bind_desc, VkVertexInputAttributeDescription* attr_desc, size_t num_attr,
VkPipelineLayout layout)
{
VkPipeline ret;
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer(vs);
Buffer fragShaderCode = File::GetBuffer(ps);
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
// 专用常量
VkSpecializationMapEntry cascadeEntry{};
cascadeEntry.constantID = 0;
cascadeEntry.offset = 0;
cascadeEntry.size = sizeof(uint32_t);
uint32_t cascadeCount = NUM_SHADOW_CASCADE;
VkSpecializationInfo specInfo{};
specInfo.mapEntryCount = 1;
specInfo.pMapEntries = &cascadeEntry;
specInfo.dataSize = sizeof(cascadeCount);
specInfo.pData = &cascadeCount;
vertShaderStageInfo.pSpecializationInfo = &specInfo;
//
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
// 顶点输入状态
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = bind_desc; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)num_attr;
vertexInputInfo.pVertexAttributeDescriptions = attr_desc; // Optional
// 顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
// 管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// 光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
// 多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
//if (OPEN_SAMPLE_SHADING)
//{
// multisampling.sampleShadingEnable = VK_TRUE;
// // min fraction for sample shading; closer to one is smooth
// multisampling.minSampleShading = .2f;
//}
// 混合模式
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;// 启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 0;
colorBlending.pAttachments = nullptr;
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;//引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = layout;//布局
pipelineInfo.renderPass = _shadow._renderPass;//渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
// 深度测试写入 开 <
// 关闭剔除
// 关闭混合
// 关闭多重采样
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&ret) != VK_SUCCESS)
{
log_damage0("图形管线(shadow)创建失败!");
return ret;
}
// 资源释放
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
return ret;
}
void VK::_create_descriptor_set_layout_shadow()
{
// ubo
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
std::array<VkDescriptorSetLayoutBinding, 1> bindings = {
uboLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_shadow._descriptorSetLayout) != VK_SUCCESS)
{
log_damage0("创建描述符布局(shadow)失败!");
return;
}
// set 0
{
size_t num = _countFrame;
std::vector<VkDescriptorSetLayout> layouts(num, _shadow._descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_shadow._descriptorSets.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _shadow._descriptorSets.data()) != VK_SUCCESS)
{
log_err0("分配描述符集(shadow)失败!");
return;
}
}
// ubo
VkDeviceSize bufferSize = sizeof(UbCSM);
_shadow._ubCsmBuffer.resize(_countFrame);
_shadow._ubCsmMemory.resize(_countFrame);
for (size_t i = 0; i < _shadow._ubCsmBuffer.size(); i++)
{
CreateBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_shadow._ubCsmBuffer[i], _shadow._ubCsmMemory[i]);
}
// 更新描述符
for (size_t i = 0; i < _countFrame; ++i)
{
// shadow ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _shadow._ubCsmBuffer[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UbCSM);
// 主管线
for (size_t j = 0; j < NUM_MAX_PRIMITIVE; ++j)
{
size_t index = j * _countFrame + i;
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSets[index];
descriptorWrites[0].dstBinding = BINDING_INDEX_CASCADE;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
// 阴影管线
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _shadow._descriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
void VK::_create_pipeline_layout_bone()
{
// 推送常量区
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(PushConstantData);
// 管线布局
std::array<VkDescriptorSetLayout, 3> dsp_set_layout = {
_descriptorSetLayout,
_descriptorSetLayoutTex,
_descriptorSetLayoutBone
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = (uint32_t)dsp_set_layout.size(); // Optional
pipelineLayoutInfo.pSetLayouts = dsp_set_layout.data(); // Optional
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_pipelineLayoutBone) != VK_SUCCESS)
{
log_damage0("创建管线布局失败!");
return;
}
}
void VK::_create_frame_buffer()
{
_allFrameBufferSwapChain.resize(_allImageViewSwapChain.size());
//
for (size_t i = 0; i < _allImageViewSwapChain.size(); i++)
{
std::array<VkImageView, 2> attachments = {
_allImageViewSwapChain[i],
_depthImageView
};
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = _renderPass2D; // 绘制流程
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = _extentSwapChain.width;
framebufferInfo.height = _extentSwapChain.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(_device, &framebufferInfo, nullptr, &_allFrameBufferSwapChain[i]) != VK_SUCCESS)
{
log_damage0("创建帧缓冲区失败!");
return;
}
}
}
void VK::_create_command_pool()
{
// 队列族
uint32_t qf_index;
if (!_find_queue_families(_physicalDevice, qf_index))
{
log_damage("设备没有合适的队列族!");
return;
}
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = qf_index;
if (vkCreateCommandPool(_device, &poolInfo, nullptr, &_commandPool) != VK_SUCCESS)
{
log_damage0("创建命令池失败!");
return;
}
}
void VK::_create_command_buffer()
{
_allCommandBuffer.resize(_countFrame);
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = _commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = (uint32_t)_countFrame;
if (vkAllocateCommandBuffers(_device, &allocInfo,
&_allCommandBuffer[_currentFrame]) != VK_SUCCESS)
{
log("创建命令缓冲区失败!");
return;
}
}
void VK::_record_command_buffer(VkCommandBuffer command_buffer, uint32_t index_image)
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; // Optional
beginInfo.pInheritanceInfo = nullptr; // Optional
// 开始记录
if (vkBeginCommandBuffer(command_buffer, &beginInfo) != VK_SUCCESS)
{
log_damage0("记录命令缓冲区失败!(Begin)");
return;
}
auto& param = Engine::GetParamRef();
if (param._show3D)
{
// 阴影贴图生成
for (size_t i = 0; i < NUM_SHADOW_CASCADE; ++i)
{
auto cascade = _shadow._cascade[i];
// ------------------- 开始阴影 RenderPass -------------------
VkRenderPassBeginInfo shadowRenderPassInfo{};
shadowRenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
shadowRenderPassInfo.renderPass = _shadow._renderPass;
shadowRenderPassInfo.framebuffer = cascade._frameBuffer; // 每个级联一个FB
shadowRenderPassInfo.renderArea.offset = { 0, 0 };
shadowRenderPassInfo.renderArea.extent = { SIZE_SHADOW_IMAGE, SIZE_SHADOW_IMAGE };
// 清空深度
VkClearValue clearDepth{};
clearDepth.depthStencil.depth = 1.0f;
clearDepth.depthStencil.stencil = 0;
shadowRenderPassInfo.clearValueCount = 1;
shadowRenderPassInfo.pClearValues = &clearDepth;
vkCmdBeginRenderPass(command_buffer, &shadowRenderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
// ------------------- 视口 & 裁剪 -------------------
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)SIZE_SHADOW_IMAGE;
viewport.height = (float)SIZE_SHADOW_IMAGE;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = { 0,0 };
scissor.extent = { SIZE_SHADOW_IMAGE, SIZE_SHADOW_IMAGE };
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
// 绘制有阴影的物品(3d)
for (std::vector<Model*>& mul : _allMulModel)
{
for (Model* model : mul)
{
RenderModel(command_buffer, model, i);
}
}
// 结束阴影渲染
vkCmdEndRenderPass(command_buffer);
}
}
// 通用视口
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)_extentSwapChain.width;
viewport.height = (float)_extentSwapChain.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
// 通用裁剪
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = _extentSwapChain;
// gfx通用绘制函数
auto fn_render_gfx = [&](bool is_2d, bool trans)
{
size_t offset = 0;
if (trans)
offset = 6;
if (is_2d)
offset += 3;
size_t index_uniform = _currentFrame + (is_2d ? _countFrame : 0);
for (size_t i = 0; i < 3; ++i)
{
size_t index = i + offset;
size_t index_pipeline = i + (trans ? 3 : 0);
// 绑定管线
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._vecGraphicsPipeline[index_pipeline]);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._pipelineLayout, 0, 1, &_gfx._descriptorSets[index_uniform], 0, nullptr);
VertexBufferGfx& vb = _gfx._arrVB[index];
VkBuffer vertexBuffers[] = { vb[_currentFrame]._vertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertexBuffers, offsets);
// 绘制
vkCmdDraw(command_buffer, (uint32_t)vb[_currentFrame]._index, 1, 0, 0);
}
};
{
// 渲染流程3d Begin
VKRenderTarget& rt = _allRenderTarget[0];
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = _renderPass3D;
renderPassInfo.framebuffer = rt._frameBuffer;
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = _extentSwapChain;
// 清屏
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[1].depthStencil = { 1.0f, 0 };
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
// 开始
vkCmdBeginRenderPass(command_buffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
// 设置视口和裁剪
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
if (param._show3D)
{
//--------------------------------skybox-------------------------------------
if (_skybox._current != -1)
{
// set 0
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_skybox._pipelineLayout, 0, 1, &_skybox._descriptorSets[0 * NUM_MAX_ACTOR + _currentFrame], 0, nullptr);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _skybox._graphicsPipeline);
const VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(command_buffer, 0, 1, &_skybox._vertexBuffer, offsets);
vkCmdBindIndexBuffer(command_buffer, _skybox._indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(command_buffer, 36, 1, 0, 0, 0);
}
//--------------------------------3d---------------------------------------
//3d
_renderInfo._numActor = 0;
_renderInfo._numDrawCall = 0;
for (std::vector<Model*>& mul : _allMulModel)
{
for (Model* model : mul)
{
RenderModel(command_buffer, model, -1);
}
}
// todo render pass 修正
////--------------------------------3d gfx------------------------------------
//// 设置视口
//vkCmdSetViewport(command_buffer, 0, 1, &viewport);
//// 设置裁剪
//vkCmdSetScissor(command_buffer, 0, 1, &scissor);
//fn_render_gfx(false, false);
//fn_render_gfx(false, true);
}
vkCmdEndRenderPass(command_buffer);
}
// 3d后处理
//--------------------------------2d---------------------------------------
{
// 渲染流程2d -> 交换链缓冲区
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = _renderPass2D;
renderPassInfo.framebuffer = _allFrameBufferSwapChain[index_image];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = _extentSwapChain;
// 清屏
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} };
clearValues[1].depthStencil = { 1.0f, 0 };
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
// 开始
vkCmdBeginRenderPass(command_buffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
// 单个dc
VkPipeline pipeline_last = 0;
_2d._renderInfo._numSwitchPso = 0;
auto fn_render_dc = [&](const std::vector<DrawCall>& list_dc, bool is_trans)
{
// 2d公共描述符
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_2d._pipelineLayout, 0, 1, &_2d._descriptorSets0[_currentFrame], 0, nullptr);
for (const DrawCall& dc : list_dc)
{
// 切换管线
VkPipeline pipeline;
if (dc._blend == Sprite::Blend::EFFECT)
pipeline = _2d._graphicsPipelineEffect;
else if (dc._blend == Sprite::Blend::GRAY)
pipeline = _2d._graphicsPipelineGray;
else
pipeline = is_trans ? _2d._graphicsPipelineTrans : _2d._graphicsPipeline;
if (pipeline != pipeline_last)
{
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
pipeline_last = pipeline;
++_2d._renderInfo._numSwitchPso;
}
// 设置视口
if (dc._viewport)
{
VkViewport viewport{};
viewport.x = (*dc._viewport)[0];
viewport.y = (*dc._viewport)[1];
viewport.width = (*dc._viewport)[2];
viewport.height = (*dc._viewport)[3];
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
}
else
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// 设置裁剪
if (dc._scissorRect)
{
VkRect2D scissor{};
scissor.offset = { (*dc._scissorRect)[0], (*dc._scissorRect)[1] };
scissor.extent = { (uint32_t)(*dc._scissorRect)[2], (uint32_t)(*dc._scissorRect)[3] };
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}
else
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
// 设置贴图
uint32_t offset_tex = (uint32_t)(dc._canvas->_id);// * _countFrame + _currentFrame);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_2d._pipelineLayout, 1, 1, &_2d._descriptorSets1[offset_tex], 0, nullptr);
// 推送常量(变换)
size_t id_coor = dc._rootCoor ? dc._rootCoor->GetRootIndex() : 0;
VK2D::CBO cbo;
cbo._model = _2d._allRootCoorMat[id_coor];
cbo._samplerIndex = (uint32_t)dc._sampler;
assert(cbo._samplerIndex < NUM_2D_SAMPLER);
vkCmdPushConstants(command_buffer, _2d._pipelineLayout,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(VK2D::CBO), &cbo);
// 绑定顶点缓冲区
VkBuffer vertexBuffers[] = { dc._canvas->_vertexBuffer[_currentFrame] };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertexBuffers, offsets);
// 绘制(注意与3d不同)
vkCmdDrawIndexed(command_buffer,
(uint32_t)((dc._end - dc._beg) / 2 * 3), 1,
0, (int32_t)dc._beg, 0);
}
};
//------------------2d 不透明----------------
if (!_2d._vecDc.empty())
{
// 绑定索引缓冲
vkCmdBindIndexBuffer(command_buffer, _2d._indexBuffer, 0, VK_INDEX_TYPE_UINT32);
fn_render_dc(_2d._vecDc, false);
}
//--------------------2d gfx 不透明----------------
// 设置视口
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// 设置裁剪
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
fn_render_gfx(true, false);
//--------------------2d 透明----------------------
if (!_2d._vecDcTrans.empty())
{
if (_2d._vecDc.empty())
{
// 绑定索引缓冲
vkCmdBindIndexBuffer(command_buffer, _2d._indexBuffer, 0, VK_INDEX_TYPE_UINT32);
}
fn_render_dc(_2d._vecDcTrans, true);
}
//--------------------2d gfx 透明----------------
// 设置视口
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// 设置裁剪
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
fn_render_gfx(true, true);
//结束
vkCmdEndRenderPass(command_buffer);
}
//结束记录
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS)
{
log_damage0("记录命令缓冲区失败!(End)");
return;
}
}
void VK::Render(GLFWwindow* window)
{
#if DL_PLATFORM == DL_PLATFORM_ANDROID
// 不绘制,但处理事件
if(g_android->_bPause || g_android->_surfaceState == 0)
return;
if(g_android->_surfaceState == 1)
{
// 状态为1则安卓surface已经创建
_rebuild_swap_chain(window);
}
#endif
// 等待GPU完成(栅栏触发)
constexpr uint64_t TIME_OUT = UINT64_MAX;// 5000000000ULL;
vkWaitForFences(_device, 1, &_allFenceInFlight[_currentFrame], VK_TRUE, TIME_OUT);
// 获得交换链图像(wait semaphore锁住)
uint32_t index_image;
VkResult result = vkAcquireNextImageKHR(_device, _swapChain, TIME_OUT,
_allSemaphoreImageAvailable[_currentFrame], VK_NULL_HANDLE, &index_image);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
{// 重建交换链
#if DL_PLATFORM == DL_PLATFORM_ANDROID
// 标记安卓surface失效
g_android->_sizeWindow = {};
#endif
_rebuild_swap_chain(window);
return;
}
else if (result != VK_SUCCESS)
{
log_damage0("获取交换链图像失败!");
return;
}
// 有提交任务才重置栅栏(避免被return掉)
vkResetFences(_device, 1, &_allFenceInFlight[_currentFrame]);
//更新统一缓冲
auto& param = Engine::GetParamRef();
if (param._show3D)
{
_update_uniform_light();
_update_uniform_buffer();
}
//记录命令
vkResetCommandBuffer(_allCommandBuffer[_currentFrame], 0);
_record_command_buffer(_allCommandBuffer[_currentFrame], index_image);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
//提交命令
VkSemaphore waitSemaphores[] = { _allSemaphoreImageAvailable[_currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &_allCommandBuffer[_currentFrame];
//设置完成信号量
VkSemaphore signalSemaphores[] = { _allSemaphoreRenderFinished[_currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
//提交(等待wait semaphore解锁,并将signal semaphore锁住)
if (vkQueueSubmit(_graphicsQueue, 1, &submitInfo, _allFenceInFlight[_currentFrame]) != VK_SUCCESS)
{
log_damage0("命令缓冲区提交失败!");
return;
}
//呈现
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = { _swapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &index_image;
presentInfo.pResults = nullptr; // Optional
// 等待signal semaphore解锁
result = vkQueuePresentKHR(_presentQueue, &presentInfo);
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
#if DL_PLATFORM == DL_PLATFORM_ANDROID
// 标记安卓surface失效
g_android->_sizeWindow = {};
#endif
_rebuild_swap_chain(window);
return;
}
else
{
log_damage0("呈现交换链图像失败!");
return;
}
}
_currentFrame = (_currentFrame + 1) % _countFrame;
}
void VK::_create_sync_objects()
{
_allSemaphoreImageAvailable.resize(_countFrame);
_allSemaphoreRenderFinished.resize(_countFrame);
_allFenceInFlight.resize(_countFrame);
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
for (size_t i = 0; i < _countFrame; ++i)
{
if (vkCreateSemaphore(_device, &semaphoreInfo, nullptr, &_allSemaphoreImageAvailable[i]) != VK_SUCCESS
|| vkCreateSemaphore(_device, &semaphoreInfo, nullptr, &_allSemaphoreRenderFinished[i]) != VK_SUCCESS
|| vkCreateFence(_device, &fenceInfo, nullptr, &_allFenceInFlight[i]) != VK_SUCCESS)
{
log_damage0("同步对象创建失败!");
return;
}
}
}
void VK::_create_command_upload()
{
// 队列族
uint32_t qf_index;
if (!_find_queue_families(_physicalDevice, qf_index, 1))
{
log_damage("设备没有合适的队列族!");
return;
}
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = qf_index;
if (vkCreateCommandPool(_device, &poolInfo, nullptr, &_commandPoolUpload) != VK_SUCCESS)
{
log_damage0("创建命令池(upload)失败!");
return;
}
}
std::vector<const char*> VK::_get_required_extensions()
{
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (ENABLE_VALIDATION_LAYERS)
{
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
return extensions;
}
void VK::_release_swap_chain()
{
vkDestroyImageView(_device, _depthImageView, nullptr);
vkDestroyImage(_device, _depthImage, nullptr);
vkFreeMemory(_device, _depthImageMemory, nullptr);
vkDestroyImageView(_device, _colorImageView, nullptr);
vkDestroyImage(_device, _colorImage, nullptr);
vkFreeMemory(_device, _colorImageMemory, nullptr);
for (auto framebuffer : _allFrameBufferSwapChain)
{
vkDestroyFramebuffer(_device, framebuffer, nullptr);
}
for (auto image_view : _allImageViewSwapChain)
{
vkDestroyImageView(_device, image_view, nullptr);
}
vkDestroySwapchainKHR(_device, _swapChain, nullptr);
}
void VK::_rebuild_swap_chain(GLFWwindow* window)
{
// 最小化(surface失效)则等待
int width = 0, height = 0;
glfwGetFramebufferSize(window, &width, &height);
while (width == 0 || height == 0)
{
glfwGetFramebufferSize(window, &width, &height);
glfwWaitEvents();
}
vkDeviceWaitIdle(_device);
_release_swap_chain();
for (auto& iter : _allRenderTarget)
{
iter.Delete(_device);
}
#if DL_PLATFORM == DL_PLATFORM_ANDROID
// 安卓需要重建surface,其他平台待观察
_create_surface(window);
#endif
_create_swap_chain(window);
_create_image_view();
_create_color_resources();
_create_depth_resources();
_create_frame_buffer();
for (size_t i = 0; i < _allRenderTarget.size(); ++i)
{
CreateRenderTargetReal(i, _allRenderTarget[i]);
UpdateCanvasRenderTarget(i, _allRenderTarget[i]);
}
}
bool VK::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory)
{
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(_device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS)
{
log_err0("创建缓冲区失败!");
return false;
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(_device, buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(_device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS)
{
log_err0("分配缓冲区内存失败!");
return false;
}
vkBindBufferMemory(_device, buffer, bufferMemory, 0);
return true;
}
void VK::CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
VkBufferCopy copyRegion{};
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
EndSingleTimeCommands(commandBuffer);
}
void VK::PopulateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo)
{
createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = CallbackDebug;
}
uint32_t VK::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(_physicalDevice, &memProperties);
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
{
if ((typeFilter & (1 << i))
&& (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
return i;
}
}
log_damage0("未找到合适的内存类型");
return 0;
}
void VK::CopyBufferToImage(VkBuffer buffer, VkImage image,
uint32_t width, uint32_t height, uint32_t mip_level)
{
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
//指定区域
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = mip_level;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = { width, height, 1 };
vkCmdCopyBufferToImage(commandBuffer, buffer, image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
EndSingleTimeCommands(commandBuffer);
}
void VK::CopyBufferToImageMulti(
const std::array<VkBuffer, NUM_MIPMAP_2D>& vec_buffer,
VkImage image, const std::array<Size, NUM_MIPMAP_2D>& vec_size)
{
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
// 指定属性
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
for (size_t i = 0; i < vec_buffer.size(); ++i)
{
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = (uint32_t)i;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = {
(uint32_t)vec_size[i][0], (uint32_t)vec_size[i][1], 1};
vkCmdCopyBufferToImage(commandBuffer, vec_buffer[i], image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
}
EndSingleTimeCommands(commandBuffer);
}
void VK::CreateImage(uint32_t w, uint32_t h, uint32_t mip_level, VkSampleCountFlagBits numSamples,
VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage,
VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory, uint32_t layers)
{
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = w;
imageInfo.extent.height = h;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = mip_level;
imageInfo.arrayLayers = layers;
imageInfo.format = format;
imageInfo.tiling = tiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = usage;
imageInfo.samples = numSamples;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateImage(_device, &imageInfo, nullptr, &image) != VK_SUCCESS)
{
log_err0("创建图像失败!");
return;
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(_device, image, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(_device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
{
log_err0("分配图像内存失败!");
return;
}
vkBindImageMemory(_device, image, imageMemory, 0);
}
size_t VK::CreateTextureReal(Image* image, bool srgb, bool delete_image)
{
assert(image);
Texture tex;
Size size = image->GetSize();
// mipmap数
tex._mipLevel = (uint32_t)(floor(log2(Select::Max(size)))) + 1;
VkDeviceSize imageSize = image->GetSizeByte();
// 复制到暂存缓冲
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
CreateBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(_device, stagingBufferMemory, 0, imageSize, 0, &data);
memcpy(data, image->GetBuffer(), (size_t)imageSize);
vkUnmapMemory(_device, stagingBufferMemory);
if (delete_image)
delete image;
VkFormat format = srgb ? DL_VK_FORMAT_SRGB_TEXTURE : DL_VK_FORMAT_UNORM_TEXTURE;
// 创建显存图像,VK_IMAGE_USAGE_TRANSFER_SRC_BIT用于生成mipmap
CreateImage((uint32_t)size[0], (uint32_t)size[1], tex._mipLevel, VK_SAMPLE_COUNT_1_BIT,
format,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
tex._image, tex._memory);
// 转换状态 为 复制目标
TransitionImageLayout(tex._image, format,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
tex._mipLevel);
// 暂存缓冲 -> 显存缓冲 (mip 0)
CopyBufferToImage(stagingBuffer, tex._image,
(uint32_t)size[0], (uint32_t)size[1], 0);
// 生成mipmap,并 转换状态 为 着色器资源
GenerateMipmaps(tex._image, format,
(int32_t)size[0], (int32_t)size[1], tex._mipLevel);
vkDestroyBuffer(_device, stagingBuffer, nullptr);
vkFreeMemory(_device, stagingBufferMemory, nullptr);
tex._imageView = CreateImageView(tex._image,
format, VK_IMAGE_ASPECT_COLOR_BIT, tex._mipLevel);
_allTexture3D.push_back(tex);
return _allTexture3D.size() - 1;
}
VkImageView VK::CreateImageView(VkImage image, VkFormat format,
VkImageAspectFlags aspectFlags, uint32_t mip_level)
{
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = format;
viewInfo.subresourceRange.aspectMask = aspectFlags;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = mip_level;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
VkImageView imageView;
if (vkCreateImageView(_device, &viewInfo, nullptr, &imageView) != VK_SUCCESS)
{
log_err0("创建图像视图失败!");
return 0;
}
return imageView;
}
VkCommandBuffer VK::BeginSingleTimeCommands()
{
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = _commandPool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(_device, &allocInfo, &commandBuffer);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
return commandBuffer;
}
void VK::EndSingleTimeCommands(VkCommandBuffer commandBuffer)
{
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(_graphicsQueue);
vkFreeCommandBuffers(_device, _commandPool, 1, &commandBuffer);
}
void VK::TransitionImageLayout(VkImage image, VkFormat format,
VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mip_level)
{
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
//图像内存屏障
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = mip_level;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = 0; // TODO
barrier.dstAccessMask = 0; // TODO
//
if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (HasStencilComponent(format))
{
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
else
{
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
//管线阶段掩码
VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED
&& newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{//普通 -> 复制目标
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
&& newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{//复制目标 -> 着色器资源
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED
&& newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
&& newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
{//交换链 -> 复制源
barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
&& newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
{//复制源 -> 交换链
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
&& newLayout == VK_IMAGE_LAYOUT_GENERAL)
{//复制目标 -> 生成
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
&& newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
{//着色器资源 -> 复制源
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
&& newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{//复制源 -> 着色器资源
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else
{
log_err0("不支持的转换!");
return;
}
vkCmdPipelineBarrier(
commandBuffer,
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
EndSingleTimeCommands(commandBuffer);
}
void VK::_create_descriptor_set_layout()
{
// ubo
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = BINDING_INDEX_UBO;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
// ubo material
VkDescriptorSetLayoutBinding uboLayoutBinding1{};
uboLayoutBinding1.binding = BINDING_INDEX_MATERIAL;
uboLayoutBinding1.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding1.descriptorCount = 1;
uboLayoutBinding1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;//像素着色器可见
uboLayoutBinding1.pImmutableSamplers = nullptr; // Optional
// ubo pass
VkDescriptorSetLayoutBinding uboLayoutBinding2{};
uboLayoutBinding2.binding = BINDING_INDEX_PASS;
uboLayoutBinding2.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding2.descriptorCount = 1;
uboLayoutBinding2.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;//像素着色器可见
uboLayoutBinding2.pImmutableSamplers = nullptr; // Optional
// ubo cascade
VkDescriptorSetLayoutBinding uboLayoutBinding3{};
uboLayoutBinding3.binding = BINDING_INDEX_CASCADE;
uboLayoutBinding3.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding3.descriptorCount = 1;
uboLayoutBinding3.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;//像素着色器可见
uboLayoutBinding3.pImmutableSamplers = nullptr; // Optional
// ibl贴图
VkDescriptorSetLayoutBinding texLayoutBinding{};
texLayoutBinding.binding = BINDING_INDEX_IBL;
texLayoutBinding.descriptorCount = 1;
texLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding.pImmutableSamplers = nullptr;
texLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// brdf贴图
VkDescriptorSetLayoutBinding texLayoutBinding1{};
texLayoutBinding1.binding = BINDING_INDEX_BRDF;
texLayoutBinding1.descriptorCount = 1;
texLayoutBinding1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding1.pImmutableSamplers = nullptr;
texLayoutBinding1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// 阴影贴图
VkDescriptorSetLayoutBinding texLayoutBinding2{};
texLayoutBinding2.binding = BINDING_INDEX_SHADOW;
texLayoutBinding2.descriptorCount = 1;
texLayoutBinding2.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding2.pImmutableSamplers = nullptr;
texLayoutBinding2.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 7> bindings = {
uboLayoutBinding, uboLayoutBinding1, uboLayoutBinding2, uboLayoutBinding3,
texLayoutBinding, texLayoutBinding1, texLayoutBinding2
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_descriptorSetLayout) != VK_SUCCESS)
{
log_damage0("创建描述符集合失败!");
return;
}
}
void VK::_create_descriptor_set_layout_texture()
{
// 漫反射贴图
VkDescriptorSetLayoutBinding texLayoutBinding0{};
texLayoutBinding0.binding = 0;
texLayoutBinding0.descriptorCount = 1;
texLayoutBinding0.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding0.pImmutableSamplers = nullptr;
texLayoutBinding0.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// 物理贴图
VkDescriptorSetLayoutBinding texLayoutBinding1{};
texLayoutBinding1.binding = 1;
texLayoutBinding1.descriptorCount = 1;
texLayoutBinding1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding1.pImmutableSamplers = nullptr;
texLayoutBinding1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// 法线贴图
VkDescriptorSetLayoutBinding texLayoutBinding2{};
texLayoutBinding2.binding = 2;
texLayoutBinding2.descriptorCount = 1;
texLayoutBinding2.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding2.pImmutableSamplers = nullptr;
texLayoutBinding2.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// AO贴图
VkDescriptorSetLayoutBinding texLayoutBinding3{};
texLayoutBinding3.binding = 3;
texLayoutBinding3.descriptorCount = 1;
texLayoutBinding3.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding3.pImmutableSamplers = nullptr;
texLayoutBinding3.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
// 自发光贴图
VkDescriptorSetLayoutBinding texLayoutBinding4{};
texLayoutBinding4.binding = 4;
texLayoutBinding4.descriptorCount = 1;
texLayoutBinding4.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding4.pImmutableSamplers = nullptr;
texLayoutBinding4.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 5> bindings = {
texLayoutBinding0, texLayoutBinding1, texLayoutBinding2,
texLayoutBinding3, texLayoutBinding4
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_descriptorSetLayoutTex) != VK_SUCCESS)
{
log_damage0("创建描述符集合(texture)失败!");
return;
}
}
void VK::_create_descriptor_set_layout_skybox()
{
// ubo
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
// ubo pass
VkDescriptorSetLayoutBinding uboLayoutBinding1{};
uboLayoutBinding1.binding = 1;
uboLayoutBinding1.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding1.descriptorCount = 1;
uboLayoutBinding1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;//像素着色器可见
uboLayoutBinding1.pImmutableSamplers = nullptr; // Optional
// skybox贴图
VkDescriptorSetLayoutBinding texLayoutBinding2{};
texLayoutBinding2.binding = 2;
texLayoutBinding2.descriptorCount = 1;
texLayoutBinding2.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding2.pImmutableSamplers = nullptr;
texLayoutBinding2.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 3> bindings = {
uboLayoutBinding, uboLayoutBinding1, texLayoutBinding2
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_skybox._descriptorSetLayout) != VK_SUCCESS)
{
log_damage0("创建描述符集合(skybox)失败!");
return;
}
}
void VK::_create_descriptor_set_layout_bone()
{
// ubo bone
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
std::array<VkDescriptorSetLayoutBinding, 1> bindings = {
uboLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_descriptorSetLayoutBone) != VK_SUCCESS)
{
log_damage0("创建描述符集合失败!");
return;
}
}
void VK::_create_uniform_buffers()
{
// ubo
VkDeviceSize bufferSize = sizeof(UbObject);
_uniformBuffers.resize(_countFrame);
_uniformBuffersMemory.resize(_countFrame);
for (size_t i = 0; i < _countFrame; i++)
{
CreateBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_uniformBuffers[i], _uniformBuffersMemory[i]);
}
// material
VkDeviceSize bufferSize1 = sizeof(Material);
constexpr size_t num = NUM_MAX_MATERIAL;
_ubMaterial.resize(num);
_ubMaterialMemory.resize(num);
for (size_t i = 0; i < num; i++)
{
CreateBuffer(bufferSize1,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_ubMaterial[i], _ubMaterialMemory[i]);
}
// pass
VkDeviceSize bufferSize2 = sizeof(UbPass);
_ubPass.resize(_countFrame);
_ubPassMemory.resize(_countFrame);
for (size_t i = 0; i < _countFrame; i++)
{
CreateBuffer(bufferSize2,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_ubPass[i], _ubPassMemory[i]);
}
_pass._light = {};
_pass._exposure = 1.0f;
_pass._gamma = 2.2f;
_pass._prefilteredCubeMipLevels = 0;
_pass._scaleIBLAmbient = 1.0f;
_pass._sh = {};
_pass._cascadeSplits = {};
_pass._debugView = 0;
}
void VK::_create_uniform_bone()
{
VkDeviceSize bufferSize = sizeof(UboBone);
const size_t num = _countFrame * NUM_MAX_BONE;
_ubBone.resize(num);
_ubBoneMemory.resize(num);
_mapBoneUse.resize(NUM_MAX_BONE, false);
for (size_t i = 0; i < num; i++)
{
CreateBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_ubBone[i], _ubBoneMemory[i]);
}
}
void VK::_create_ibl()
{
// 环境贴图采样器
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
// 超过取边缘色
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
// 无需各向异性
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; // 不需要
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f; // 不需要mip
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_skybox._envSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器(skybox env)失败!");
return;
}
}
// ibl贴图采样器
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
// 超过取边缘色
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
// 无需各向异性
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; // 线性
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = VK_LOD_CLAMP_NONE; // 允许所有层级
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_skybox._iblSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器(skybox ibl)失败!");
return;
}
}
// bdrf贴图采样器
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
// 超过取边缘色
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
// 无需各向异性
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; // 不需要
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f; // 允许所有层级
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_skybox._brdfSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器(skybox brdf)失败!");
return;
}
}
// brdf贴图
{
_create_texture_ktx("dl/brdf.ktx", _skybox._texBrdf);
}
// 更新描述符
{
// brdf (正常管线)
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = _skybox._texBrdf._imageView;
imageInfo.sampler = _skybox._brdfSampler;
for (size_t i = 0; i < _descriptorSets.size(); ++i)
{
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSets[i];
descriptorWrites[0].dstBinding = BINDING_INDEX_BRDF;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
}
//
//void VK::_create_texture_ktx(std::string_view path, Texture& tex)
//{
// Buffer buf = File::GetBuffer(path);
//
// ktxTexture* texture;
// KTX_error_code result;
//
// result = ktxTexture_CreateFromMemory(path.data(),
// KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT,
// &texture);
// if (result != KTX_SUCCESS)
// {
// log_err0("解析ktx贴图失败!");
// return;
// }
// // 基础信息
// ktx_uint32_t num_level = texture->numLevels;
// ktx_uint32_t base_width = texture->baseWidth;
// ktx_bool_t is_array = texture->isArray;
//
// // 切片
// ktx_uint32_t level = 1;
// ktx_uint32_t layer = 0;
// ktx_uint32_t face_slice = 3;
// ktx_size_t offset;
//
// result = ktxTexture_GetImageOffset(texture, level, layer, face_slice, &offset);
// if (result != KTX_SUCCESS)
// {
// log_err0("获取ktx贴图信息失败!");
// return;
// }
//
// ktx_uint8_t* image = ktxTexture_GetData(texture) + offset;
// // ...
// // Do something with the texture image.
// // ...
// ktxTexture_Destroy(texture);
//
//
// log_msg("ktx[{}]: mip {}, layer {}, depth {}",
// path, num_level, layer, face_slice);
//
// VkFormat format = GetVulkanFormat(tc.format);
//
// VkImage image;
// VkImageCreateInfo imageInfo{};
// imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
// imageInfo.imageType = VK_IMAGE_TYPE_2D;
// imageInfo.extent.width = tc.width;
// imageInfo.extent.height = tc.height;
// imageInfo.extent.depth = 1;
// imageInfo.mipLevels = tc.num_mips;
// imageInfo.arrayLayers = 1;
// imageInfo.format = format;
// imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
// imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
// imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
// imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
// imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
// imageInfo.flags = 0;
//
// if (vkCreateImage(_device, &imageInfo, nullptr, &image) != VK_SUCCESS)
// {
// log_err0("创建图像失败!");
// return;
// }
//
// VkMemoryRequirements memRequirements;
// vkGetImageMemoryRequirements(_device, image, &memRequirements);
//
// VkMemoryAllocateInfo allocInfo{};
// allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
// allocInfo.allocationSize = memRequirements.size;
// allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits,
// VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
//
// VkDeviceMemory imageMemory;
// if (vkAllocateMemory(_device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS)
// {
// log_err0("分配图像内存失败!");
// return;
// }
// vkBindImageMemory(_device, image, imageMemory, 0);
//
//
// // 转换状态 为 复制目标
// uint32_t num_mip = (uint32_t)tc.num_mips;
// TransitionImageLayout(image, format,
// VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
// num_mip);
// for (uint32_t mip_level = 0; mip_level < num_mip; ++mip_level)
// {
// ddsktx_sub_data sub_data;
// ddsktx_get_sub(&tc, &sub_data, buf.data(), (int)buf.size(), 0, 0, mip_level);
// if (ddsktx_format_compressed(tc.format))
// assert(0);
//
// VkDeviceSize imageSize = sub_data.size_bytes;
// // 复制到暂存缓冲
// VkBuffer stagingBuffer;
// VkDeviceMemory stagingBufferMemory;
// CreateBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
// VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
// stagingBuffer, stagingBufferMemory);
//
// void* data;
// vkMapMemory(_device, stagingBufferMemory, 0, imageSize, 0, &data);
// memcpy(data, sub_data.buff, (size_t)imageSize);
// vkUnmapMemory(_device, stagingBufferMemory);
//
// // 暂存缓冲 -> 显存缓冲
// CopyBufferToImage(stagingBuffer, image,
// (uint32_t)tc.width, (uint32_t)tc.height, mip_level);
//
// vkDestroyBuffer(_device, stagingBuffer, nullptr);
// vkFreeMemory(_device, stagingBufferMemory, nullptr);
// }
// // 换状态 为 着色器资源
// TransitionImageLayout(image, format,
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
// num_mip);
// //
// VkImageViewCreateInfo viewInfo{};
// viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
// viewInfo.image = image;
// viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
// viewInfo.format = GetVulkanFormat(tc.format);
// viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
// viewInfo.subresourceRange.baseMipLevel = 0;
// viewInfo.subresourceRange.levelCount = 1;
// viewInfo.subresourceRange.baseArrayLayer = 0;
// viewInfo.subresourceRange.layerCount = 1;
//
// VkImageView imageView;
// if (vkCreateImageView(_device, &viewInfo, nullptr, &imageView) != VK_SUCCESS)
// {
// log_err0("创建图像视图失败!");
// return;
// }
//
// tex._image = image;
// tex._memory = imageMemory;
// tex._imageView = imageView;
// tex._width = tc.width;
// tex._height = tc.height;
// tex._mipLevel = tc.num_mips;
//}
void VK::_create_texture_ktx(std::string_view path, Texture& tex)
{
Buffer buf = File::GetBuffer(path);
ktxTexture* kTexture;
KTX_error_code result;
ktxVulkanDeviceInfo vdi;
ktxVulkanTexture texture;
// 构造Device数据
result = ktxVulkanDeviceInfo_Construct(&vdi, _physicalDevice, _device,
_transferQueue, _commandPoolUpload, nullptr);
if (result != KTX_SUCCESS)
{
log_err("ktx解析失败(info):{}", path);
return;
}
result = ktxTexture_CreateFromMemory((ktx_uint8_t*)buf.data(), buf.size(),
KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT,
&kTexture);
if (result != KTX_SUCCESS)
{
log_err("ktx解析失败(create):{}", path);
return;
}
// 1.检查纹理是否需要转码
if (ktxTexture_NeedsTranscoding(kTexture))
{
// 2.选择转码目标格式
// 这里以 RGBA 32位 为例,这是最通用的后备方案,但建议根据硬件选择ASTC/BC7等压缩格式
ktx_transcode_fmt_e targetFormat = KTX_TTF_RGBA32;
// 3.执行转码
result = ktxTexture2_TranscodeBasis((ktxTexture2*)(kTexture), targetFormat, 0);
if (result != KTX_SUCCESS)
{
log_err("转码Basis失败:{}", path);
// 释放资源并返回
ktxTexture_Destroy(kTexture);
return;
}
}
result = ktxTexture_VkUploadEx(kTexture, &vdi, &texture,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (result != KTX_SUCCESS)
{
log_err("ktx解析失败(upload):{}", path);
return;
}
ktxTexture_Destroy(kTexture);
ktxVulkanDeviceInfo_Destruct(&vdi);
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = texture.image;
viewInfo.viewType = texture.viewType;
viewInfo.format = texture.imageFormat;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = texture.levelCount;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = texture.layerCount;
VkImageView imageView;
if (vkCreateImageView(_device, &viewInfo, nullptr, &imageView) != VK_SUCCESS)
{
log_err0("创建图像视图失败!");
return;
}
log_msg("加载tkx纹理 [{}]:\n mip数:{}\n大小:{}*{}\n格式:{}",
path, texture.levelCount, /*texture.layerCount, texture.depth, */
texture.width, texture.height, magic_enum::enum_name(texture.imageFormat));
tex._image = texture.image;
tex._memory = texture.deviceMemory;
tex._imageView = imageView;
tex._width = texture.width;
tex._height = texture.height;
tex._mipLevel = texture.levelCount;
// 后续通过tex释放,不使用以下代码
// ...
// Vulkan rendering using the texture
// ...
// When done using the image in Vulkan...
//ktxVulkanTexture_Destruct(&texture, _device, nullptr);
}
void VK::_create_descriptor_pool()
{
std::array<VkDescriptorPoolSize, 4> poolSizes{};
uint32_t num = (uint32_t)(NUM_MAX_PRIMITIVE * _countFrame);
uint32_t num_all = 0;
// set 0
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = (num * 3 +
_countFrame +// shadow
_countFrame)*10; // skybox
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = num * 2;
// set 1
poolSizes[2].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[2].descriptorCount = (uint32_t)(NUM_MAX_PRIMITIVE * 5);
// set 2
poolSizes[3].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[3].descriptorCount = (uint32_t)(NUM_MAX_BONE * _countFrame);
for (auto& iter : poolSizes)
{
num_all += iter.descriptorCount;
}
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = (uint32_t)poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = num_all * 10; //todo
if (vkCreateDescriptorPool(_device, &poolInfo, nullptr, &_descriptorPool) != VK_SUCCESS)
{
log_err0("创建描述符池失败!");
return;
}
}
void VK::_create_descriptor_sets()
{
// set 0
{
size_t num = NUM_MAX_PRIMITIVE * _countFrame;
std::vector<VkDescriptorSetLayout> layouts(num, _descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_descriptorSets.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _descriptorSets.data()) != VK_SUCCESS)
{
log_err0("分配描述符集失败!");
return;
}
}
// set 1
{
size_t num = NUM_MAX_PRIMITIVE;
std::vector<VkDescriptorSetLayout> layouts(num, _descriptorSetLayoutTex);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_descriptorSetsTex.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _descriptorSetsTex.data()) != VK_SUCCESS)
{
log_err0("分配描述符集(bone)失败!");
return;
}
}
// set 2
{
size_t num = _countFrame * NUM_MAX_BONE;
std::vector<VkDescriptorSetLayout> layouts(num, _descriptorSetLayoutBone);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_descriptorSetsBone.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _descriptorSetsBone.data()) != VK_SUCCESS)
{
log_err0("分配描述符集(bone)失败!");
return;
}
}
// 立马绑定
for (size_t j = 0; j < NUM_MAX_BONE; ++j)
{
for (size_t i = 0; i < _countFrame; i++)
{
size_t index = j * _countFrame + i;
// ubo bone
VkDescriptorBufferInfo bufferInfo2{};
bufferInfo2.buffer = _ubBone[index];
bufferInfo2.offset = 0;
bufferInfo2.range = sizeof(UboBone);
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSetsBone[index];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo2;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
}
void VK::_create_texture_sampler()
{
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.anisotropyEnable = VK_TRUE;
VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(_physicalDevice, &properties);
if (true)
{
samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
}
else
{
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
}
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_standardSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器失败!");
return;
}
}
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_pointSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器1失败!");
return;
}
}
}
void VK::_update_uniform_buffer()
{
UbObject ubo{};
Matrix4 mat_view = _camera->GetMatrixView();
float near_cilp = 0.5f;
float far_cilp = 1000.0f;
Matrix4 mat_proj = Mat::CreatePerspective(
(Float)Math::PI(1, 4), _extentSwapChain.width / (float)_extentSwapChain.height,
near_cilp, far_cilp);
ubo._proj = mat_proj;
ubo._view = mat_view;
ubo._camPos = _camera->GetPosition();
// 3d
{
void* data;
vkMapMemory(_device, _uniformBuffersMemory[_currentFrame], 0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(_device, _uniformBuffersMemory[_currentFrame]);
}
// 3d gfx
{
VKGfx::UBO ubo_gfx;
ubo_gfx._viewProj = ubo._proj * ubo._view;
void* data;
vkMapMemory(_device, _gfx._uniformBuffersMemory[_currentFrame], 0, sizeof(ubo_gfx), 0, &data);
memcpy(data, &ubo_gfx, sizeof(ubo_gfx));
vkUnmapMemory(_device, _gfx._uniformBuffersMemory[_currentFrame]);
}
// shadow
if(_renderInfo._numLightDir)
{
// 存储每个级联的分割比例(0~1)
float cascadeSplits[NUM_SHADOW_CASCADE];
// 相机视锥体总深度范围
float clipRange = far_cilp - near_cilp;
float minZ = near_cilp;
float maxZ = near_cilp + clipRange;
float range = maxZ - minZ;
// 远/近裁剪面比值(用于对数分割)
float ratio = maxZ / minZ;
// 输出 4 个 VP
UbCSM ubo{};
//
float cascadeSplitLambda = 0.95f;
for (uint32_t i = 0; i < NUM_SHADOW_CASCADE; ++i)
{
// 归一化比例:第 i+1 个级联 / 总级联数 (0~1)
float p = (i + 1) / (float)NUM_SHADOW_CASCADE;
// 对数分割:近处分割密、远处分割疏(保证近处精度)
float log = minZ * std::pow(ratio, p);
// 线性分割:均匀分割
float uniform = minZ + range * p;
// 混合系数 cascadeSplitLambda (0~1):
// 0=纯线性,1=纯对数,通常用 0.5~0.9
float d = cascadeSplitLambda * (log - uniform) + uniform;
// 归一化到 [0,1],存储为相对相机深度的分割比例
cascadeSplits[i] = (d - near_cilp) / clipRange;
}
float lastSplitDist = 0.0;
for (uint32_t i = 0; i < NUM_SHADOW_CASCADE; ++i)
{
float splitDist = cascadeSplits[i];
// 视锥体角点(主相机NDC)
Position3 frustumCorners[8] = {
{ -1.0f, -1.0f, 0.0f}, // 近左上
{ 1.0f, -1.0f, 0.0f}, // 近右上
{ 1.0f, 1.0f, 0.0f}, // 近右下
{ -1.0f, 1.0f, 0.0f}, // 近左下
{ -1.0f, -1.0f, 1.0f}, // 远左上
{ 1.0f, -1.0f, 1.0f}, // 远右上
{ 1.0f, 1.0f, 1.0f}, // 远右下
{ -1.0f, 1.0f, 1.0f}, // 远左下
};
// 逆矩阵:NDC → 世界空间
Matrix4 invCam = Mat::GetInverse(mat_proj * mat_view);
for (size_t j = 0; j < 8; ++j)
{
// 齐次坐标变换
Position4 invCorner = invCam * toLonger(frustumCorners[j], 1.0f);
// 透视除法,得到世界空间坐标
frustumCorners[j] = toShorter(invCorner / invCorner.w);
}
// 当前视锥体大小
for (uint32_t j = 0; j < 4; j++)
{
Position3 dist = frustumCorners[j + 4] - frustumCorners[j];
frustumCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
frustumCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
}
// 8个角点平均 = 视锥体中心
Position3 frustumCenter = {};
for (uint32_t j = 0; j < 8; j++)
{
frustumCenter += frustumCorners[j];
}
frustumCenter /= 8.0f;
// 计算中心到最远角点的距离 = 包围球半径
float radius = 0.0f;
for (uint32_t j = 0; j < 8; j++)
{
float distance = Math::Distance(frustumCorners[j] - frustumCenter);
radius = std::max(radius, distance);
}
// 向上取16分之一对齐,避免阴影闪烁(重要!)
radius = std::ceil(radius * 16.0f) / 16.0f;
// 正交投影的包围盒(正方体,保证无拉伸)
Position3 maxExtents = Fill::ArrayN<float, 3>(radius);
Position3 minExtents = -maxExtents;
// 光源方向(平行光,单位向量)
Position3 lightDir = _pass._light[0]._direction;
Math::Normalize(lightDir);
// 正交投影矩阵:刚好包裹包围球(世界坐标系,模型 -> 灯光,所以应该在包围球中间)
Matrix4 lightOrthoMatrix = Mat::CreateOrthogonal(
-radius, radius, radius, -radius,
radius, -radius
);
// 光源在盒子中心
Matrix4 lightViewMatrix = Mat::CreateLookTo(
frustumCenter,// - lightDir * radius, // 盒子中心
lightDir, // 观察方向
AXIS_UP // 上方向
);
// 存储级联的深度(用于着色器判断像素属于哪个级联,为负值)
_pass._cascadeSplits[i] = (near_cilp + splitDist * clipRange) * -1.0f;
// 光源VP矩阵:着色器采样阴影贴图用
ubo._viewProj[i] = lightOrthoMatrix * lightViewMatrix;
// 更新上一个分割距离,给下一级使用
lastSplitDist = cascadeSplits[i];
}
void* data;
vkMapMemory(_device, _shadow._ubCsmMemory[_currentFrame], 0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(_device, _shadow._ubCsmMemory[_currentFrame]);
}
// 3d pass
{
void* data;
vkMapMemory(_device, _ubPassMemory[_currentFrame], 0, sizeof(_pass), 0, &data);
memcpy(data, &_pass, sizeof(_pass));
vkUnmapMemory(_device, _ubPassMemory[_currentFrame]);
}
}
void VK::_update_uniform_light()
{
_renderInfo._numLightDir = _allLightDir.size();
_renderInfo._numLightDot = _allLightDot.size();
_renderInfo._numLightSpot = _allLightSpot.size();
// Dir
for (size_t i = 0; i < NUM_MAX_LIGHT_DIR; ++i)
{
Light& light = _pass._light[i];
if (i < _allLightDir.size())
{
auto iter = _allLightDir[i];
light._strength = iter._s;
light._direction = iter._d;
}
else
{
light._strength = { 0.0f, 0.0f, 0.0f };
}
}
// Dot
for (size_t i = 0; i < NUM_MAX_LIGHT_DOT; ++i)
{
Light& light = _pass._light[i + NUM_MAX_LIGHT_DIR];
if (i < _allLightDot.size())
{
auto iter = _allLightDot[i];
light._strength = iter._s;
light._position = iter._p;
light._falloffStart = iter._falloffStart;
light._falloffEnd = iter._falloffEnd;
}
else
{
light._falloffEnd = 0;
}
}
// Spot
for (size_t i = 0; i < NUM_MAX_LIGHT_SPOT; ++i)
{
Light& light = _pass._light[i + NUM_MAX_LIGHT_DIR + NUM_MAX_LIGHT_DOT];
if (i < _allLightSpot.size())
{
auto iter = _allLightSpot[i];
light._strength = iter._s;
light._position = iter._p;
light._direction = iter._d;
light._falloffStart = iter._falloffStart;
light._falloffEnd = iter._falloffEnd;
light._spotPower = iter._power;
}
else
{
light._falloffEnd = 0;
}
}
if (_allLightDir.size() >= NUM_MAX_LIGHT_DIR)
log_warn("平行光绘制数量过多:{}/{}", _allLightDir.size(), NUM_MAX_LIGHT_DIR);
if (_allLightDot.size() >= NUM_MAX_LIGHT_DOT)
log_warn("点光源绘制数量过多:{}/{}", _allLightDot.size(), NUM_MAX_LIGHT_DOT);
if (_allLightSpot.size() >= NUM_MAX_LIGHT_SPOT)
log_warn("聚光灯绘制数量过多:{}/{}", _allLightSpot.size(), NUM_MAX_LIGHT_SPOT);
_allLightDir.clear();
_allLightDot.clear();
_allLightSpot.clear();
}
VkFormat VK::FindSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
{
for (VkFormat format : candidates)
{
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR
&& (props.linearTilingFeatures & features) == features)
{
return format;
}
else if (tiling == VK_IMAGE_TILING_OPTIMAL
&& (props.optimalTilingFeatures & features) == features)
{
return format;
}
}
log_damage0("查找支持的格式失败!");
return VK_FORMAT_UNDEFINED;
}
VkFormat VK::FindDepthFormat()
{
return FindSupportedFormat(
{ VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
size_t VK::CreatePrimitive(ModelMaterial& m)
{
size_t j = _allPrimitive.size();
_allPrimitive.push_back({});
Primitive& pri = _allPrimitive[j];
pri._idMaterial = CreateMaterial(m._material);
pri._idTexDiffuse = CreateTexture(m._pathTexDiffuse);
pri._idTexPhysical = CreateTexture(m._pathTexPhysical, false);
pri._idTexNormal = CreateTexture(m._pathTexNormal, false);
pri._idTexAo = CreateTexture(m._pathTexAo, false);
pri._idTexEmissive = CreateTexture(m._pathTexEmissvie, false);
for (size_t i = 0; i < _countFrame; i++)
{
size_t index = j * _countFrame + i;
// ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UbObject);
// ubo material
VkDescriptorBufferInfo bufferInfo1{};
bufferInfo1.buffer = _ubMaterial[pri._idMaterial];
bufferInfo1.offset = 0;
bufferInfo1.range = sizeof(Material);
// ubo pass
VkDescriptorBufferInfo bufferInfo2{};
bufferInfo2.buffer = _ubPass[i];
bufferInfo2.offset = 0;
bufferInfo2.range = sizeof(UbPass);
std::array<VkWriteDescriptorSet, 3> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSets[index];
descriptorWrites[0].dstBinding = BINDING_INDEX_UBO;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = _descriptorSets[index];
descriptorWrites[1].dstBinding = BINDING_INDEX_MATERIAL;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pBufferInfo = &bufferInfo1;
descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[2].dstSet = _descriptorSets[index];
descriptorWrites[2].dstBinding = BINDING_INDEX_PASS;
descriptorWrites[2].dstArrayElement = 0;
descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[2].descriptorCount = 1;
descriptorWrites[2].pBufferInfo = &bufferInfo2;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
{
std::array<VkWriteDescriptorSet, 5> descriptorWrites{};
// 纹理
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = _allTexture3D[pri._idTexDiffuse]._imageView;
imageInfo.sampler = _standardSampler;
// 纹理1
VkDescriptorImageInfo imageInfo1{};
imageInfo1.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo1.imageView = _allTexture3D[pri._idTexPhysical]._imageView;
imageInfo1.sampler = _standardSampler;
// 纹理2
VkDescriptorImageInfo imageInfo2{};
imageInfo2.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo2.imageView = _allTexture3D[pri._idTexNormal]._imageView;
imageInfo2.sampler = _standardSampler;
// 纹理3
VkDescriptorImageInfo imageInfo3{};
imageInfo3.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo3.imageView = _allTexture3D[pri._idTexAo]._imageView;
imageInfo3.sampler = _standardSampler;
// 纹理4
VkDescriptorImageInfo imageInfo4{};
imageInfo4.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo4.imageView = _allTexture3D[pri._idTexEmissive]._imageView;
imageInfo4.sampler = _standardSampler;
//
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSetsTex[j];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = _descriptorSetsTex[j];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo1;
descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[2].dstSet = _descriptorSetsTex[j];
descriptorWrites[2].dstBinding = 2;
descriptorWrites[2].dstArrayElement = 0;
descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[2].descriptorCount = 1;
descriptorWrites[2].pImageInfo = &imageInfo2;
descriptorWrites[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[3].dstSet = _descriptorSetsTex[j];
descriptorWrites[3].dstBinding = 3;
descriptorWrites[3].dstArrayElement = 0;
descriptorWrites[3].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[3].descriptorCount = 1;
descriptorWrites[3].pImageInfo = &imageInfo3;
descriptorWrites[4].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[4].dstSet = _descriptorSetsTex[j];
descriptorWrites[4].dstBinding = 4;
descriptorWrites[4].dstArrayElement = 0;
descriptorWrites[4].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[4].descriptorCount = 1;
descriptorWrites[4].pImageInfo = &imageInfo4;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
return j;
}
Model* VK::CreateModel(ModelObject* object)
{
if (object->_allIndex.empty())
{
log_err("无效模型!");
return nullptr;
}
Model* model = new Model;
model->_allAnimation = object->_allAnimation;
model->_allSkin = object->_allSkin;
model->_allSub = object->_allSub;
model->_treeNode = object->_treeNode;
//顶点缓冲
if (!object->_allSkin.empty())
{
if (object->_allVertexBone.empty())
{
log_err("无效模型!");
return nullptr;
}
CreateVertexBufferGPU(
object->_allVertexBone, model->_vertexBuffer, model->_vertexBufferMemory);
}
else
{
if (object->_allVertex.empty())
{
log_err("无效模型!");
return nullptr;
}
CreateVertexBufferGPU(
object->_allVertex, model->_vertexBuffer, model->_vertexBufferMemory);
}
//索引缓冲
CreateIndexBuffer(
object->_allIndex, model->_indexBuffer, model->_indexBufferMemory);
// 生成材质实例
std::vector<size_t> vec_material_id;
vec_material_id.resize(object->_allMaterial.size());
for (size_t i = 0; i < object->_allMaterial.size(); ++i)
{
ModelMaterial& m = object->_allMaterial[i];
vec_material_id[i] = CreatePrimitive(m);
}
// 映射材质id
for (ModelDrawCall& sub : model->_allSub)
{
if (sub._indexMaterial != -1)
{
sub._indexMaterial = vec_material_id[sub._indexMaterial];
}
}
return model;
}
void VK::RenderModel(VkCommandBuffer command_buffer, Model* model, size_t shadow)
{
if (!model || model->_mulInstance.empty())
return;
bool has_skin = !model->_allSkin.empty();
VkPipeline* pipe;
VkPipelineLayout* pipe_layout;
bool not_shadow = shadow == (size_t)-1;
if (not_shadow)
{
pipe = !has_skin ? &_graphicsPipeline : &_graphicsPipelineBone;
pipe_layout = !has_skin ? &_pipelineLayout : &_pipelineLayoutBone;
}
else
{
pipe = !has_skin ? &_shadow._pipeline : &_shadow._pipelineBone;
pipe_layout = !has_skin ? &_shadow._layout : &_shadow._layout;
}
//绑定管线
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipe);
//绑定顶点缓冲区
VkBuffer vertexBuffers[] = { model->_vertexBuffer };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertexBuffers, offsets);
//绑定索引缓冲
vkCmdBindIndexBuffer(command_buffer, model->_indexBuffer, 0, VK_INDEX_TYPE_UINT32);
//
for (Model::Instance& node : model->_mulInstance)
{
// 推送常量(变换)
if (not_shadow)
{
vkCmdPushConstants(command_buffer, *pipe_layout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(PushConstantData), &_allPushConstant[node._idPerObject]);
}
else
{
PushConstantCSM push;
push._model = _allPushConstant[node._idPerObject]._model;
push._cascadeIndex = (uint32_t)shadow;
vkCmdPushConstants(command_buffer, *pipe_layout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(PushConstantCSM), &push);
}
// 绑定骨骼 set 2
if (has_skin)
{
assert(node._idBone != -1);
uint32_t offset = (uint32_t)(node._idBone * _countFrame
+ _currentFrame);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
*pipe_layout, 2, 1, &_descriptorSetsBone[offset], 0, nullptr);
}
for (ModelDrawCall& sub : model->_allSub)
{
uint32_t offset = (uint32_t)(sub._indexMaterial * _countFrame
+ _currentFrame);
// 绑定 set 0
if (not_shadow)
{
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
*pipe_layout, 0, 1, &_descriptorSets[offset], 0, nullptr);
}
else
{
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
*pipe_layout, 0, 1, &_shadow._descriptorSets[_currentFrame], 0, nullptr);
}
// 绑定纹理 set 1
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
*pipe_layout, 1, 1, &_descriptorSetsTex[sub._indexMaterial], 0, nullptr);
//绘制
vkCmdDrawIndexed(command_buffer,
(uint32_t)(sub._range._countTriangle * 3), 1,
(uint32_t)(sub._range._offsetIndex), 0, 0);
if (not_shadow)
++_renderInfo._numDrawCall;
}
if (not_shadow)
++_renderInfo._numActor;
}
//清空
if(not_shadow)
model->_mulInstance.clear();
}
void VK::_create_2d()
{
//------------------------------2d--------------------------------
// 0.描述符布局
//-------------------------set 0 : ubo + sampler3
// ubo
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
// 采样器数组
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
samplerLayoutBinding.descriptorCount = 3; // 三个采样器
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;// 片段阶段使用
samplerLayoutBinding.pImmutableSamplers = nullptr;
std::array<VkDescriptorSetLayoutBinding, 2> bindings0 = {
uboLayoutBinding, samplerLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings0.size();
layoutInfo.pBindings = bindings0.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_2d._descriptorSetLayout0) != VK_SUCCESS)
{
log_damage0("创建描述符集合失败!");
return;
}
//-------------------------set 1 : texture
// 贴图
VkDescriptorSetLayoutBinding texLayoutBinding{};
texLayoutBinding.binding = 0;
texLayoutBinding.descriptorCount = 1;
texLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
texLayoutBinding.pImmutableSamplers = nullptr;
texLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 1> bindings1 = {
texLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo1{};
layoutInfo1.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo1.bindingCount = (uint32_t)bindings1.size();
layoutInfo1.pBindings = bindings1.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo1, nullptr,
&_2d._descriptorSetLayout1) != VK_SUCCESS)
{
log_damage0("创建描述符集合1失败!");
return;
}
// 2.管线布局
// 推送常量区
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(VK2D::CBO);
// 管线布局
std::array<VkDescriptorSetLayout, 2> setLayouts = {
_2d._descriptorSetLayout0, // set 0
_2d._descriptorSetLayout1 // set 1
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = (uint32_t)setLayouts.size();
pipelineLayoutInfo.pSetLayouts = setLayouts.data();
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_2d._pipelineLayout) != VK_SUCCESS)
{
log_damage0("创建2d管线布局失败!");
return;
}
// 3.纹理采样器
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.anisotropyEnable = VK_TRUE;
//VkPhysicalDeviceProperties properties{};
//vkGetPhysicalDeviceProperties(_physicalDevice, &properties);
//// 2d不应该开启各向异性采样
//if (false)
//{
// samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
//}
//else
//{
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
//}
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0;
samplerInfo.maxLod = NUM_MIPMAP_2D;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_2d._textureSampler) != VK_SUCCESS)
{
log_damage0("创建2d纹理采样器失败!");
return;
}
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_2d._textureSamplerPixel) != VK_SUCCESS)
{
log_damage0("创建2d纹理采样器(pixel)失败!");
return;
}
// 关闭mipmap
samplerInfo.maxLod = 0;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_2d._textureSamplerUI) != VK_SUCCESS)
{
log_damage0("创建2d纹理采样器(ui)失败!");
return;
}
//3.5 索引缓冲
std::vector<uint32_t> indices;
indices.resize(NUM_2D_INDEX);
uint32_t n = 0;
for (uint32_t i = 0; i < NUM_2D_INDEX; i += 6)
{
indices[i + 0] = 0 + n;
indices[i + 1] = 1 + n;
indices[i + 2] = 2 + n;
indices[i + 3] = 0 + n;
indices[i + 4] = 2 + n;
indices[i + 5] = 3 + n;
n += 4;
}
CreateIndexBuffer(indices, _2d._indexBuffer, _2d._indexBufferMemory);
// 4.统一缓冲
VkDeviceSize bufferSize = sizeof(VK2D::UBO);
_2d._uniformBuffers.resize(_countFrame);
_2d._uniformBuffersMemory.resize(_countFrame);
_2d._uniformBuffersMapped.resize(_countFrame);
for (size_t i = 0; i < _countFrame; i++)
{
CreateBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_2d._uniformBuffers[i], _2d._uniformBuffersMemory[i]);
if(USE_MAPPED_2D_UBO)
vkMapMemory(_device, _2d._uniformBuffersMemory[i], 0, bufferSize, 0, &_2d._uniformBuffersMapped[i]);
}
// 5.描述符池
std::array<VkDescriptorPoolSize, 3> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = _countFrame;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
poolSizes[1].descriptorCount = _countFrame * NUM_2D_SAMPLER;
poolSizes[2].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
poolSizes[2].descriptorCount = NUM_MAX_DRAW_CALL_2D;
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = (uint32_t)poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = (uint32_t)(_countFrame + NUM_MAX_DRAW_CALL_2D);
if (vkCreateDescriptorPool(_device, &poolInfo, nullptr, &_2d._descriptorPool) != VK_SUCCESS)
{
log_err0("创建描述符池失败!");
return;
}
// 6.分配描述符
{
std::vector<VkDescriptorSetLayout> layouts(_countFrame, _2d._descriptorSetLayout0);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _2d._descriptorPool;
allocInfo.descriptorSetCount = _countFrame;
allocInfo.pSetLayouts = layouts.data();
_2d._descriptorSets0.resize(allocInfo.descriptorSetCount);
if (vkAllocateDescriptorSets(_device, &allocInfo, _2d._descriptorSets0.data()) != VK_SUCCESS)
{
log_err0("分配2d描述符集失败!");
return;
}
}
{
std::vector<VkDescriptorSetLayout> layouts(NUM_MAX_DRAW_CALL_2D, _2d._descriptorSetLayout1);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _2d._descriptorPool;
allocInfo.descriptorSetCount = NUM_MAX_DRAW_CALL_2D;
allocInfo.pSetLayouts = layouts.data();
_2d._descriptorSets1.resize(allocInfo.descriptorSetCount);
if (vkAllocateDescriptorSets(_device, &allocInfo, _2d._descriptorSets1.data()) != VK_SUCCESS)
{
log_err0("分配2d描述符集1失败!");
return;
}
}
// 更新描述符(全局)
for (size_t i = 0; i < _countFrame; ++i)
{
// ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _2d._uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(VK2D::UBO);
// 采样器
std::array<VkDescriptorImageInfo, 3> samplerInfos{};
samplerInfos[0].sampler = _2d._textureSampler;
samplerInfos[1].sampler = _2d._textureSamplerPixel;
samplerInfos[2].sampler = _2d._textureSamplerUI;
for (auto& info : samplerInfos)
{
info.imageView = VK_NULL_HANDLE;
info.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
}
//
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _2d._descriptorSets0[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = _2d._descriptorSets0[i];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
descriptorWrites[1].descriptorCount = (uint32_t)samplerInfos.size();
descriptorWrites[1].pImageInfo = samplerInfos.data();
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
//
for (auto& iter : _2d._allRootCoor)
{
iter = nullptr;
}
for (auto& iter : _2d._allRootCoorMat)
{
iter.Identity();
}
for (auto& iter : _2d._allCBO)
{
iter._model.Identity();
iter._samplerIndex = 0;
}
}
void VK::_delete_2d()
{
for (auto& iter : _2d._allRootCoor)
{
if(iter)
iter->_rootIndex = -1;
delete iter;
}
vkDestroySampler(_device, _2d._textureSampler, nullptr);
vkDestroySampler(_device, _2d._textureSamplerPixel, nullptr);
vkDestroySampler(_device, _2d._textureSamplerUI, nullptr);
for (auto& iter : _2d._allCanvas)
{
iter.second->Delete(_device);
delete iter.second;
}
//索引缓冲
vkDestroyBuffer(_device, _2d._indexBuffer, nullptr);
vkFreeMemory(_device, _2d._indexBufferMemory, nullptr);
//ub
for (size_t i = 0; i < _countFrame; i++)
{
vkDestroyBuffer(_device, _2d._uniformBuffers[i], nullptr);
vkFreeMemory(_device, _2d._uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorPool(_device, _2d._descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _2d._descriptorSetLayout1, nullptr);
vkDestroyDescriptorSetLayout(_device, _2d._descriptorSetLayout0, nullptr);
vkDestroyPipelineLayout(_device, _2d._pipelineLayout, nullptr);
}
dl::Coor* VK::GetRootCoor(size_t index)
{
if (index >= NUM_MAX_ROOT_COOR)
return nullptr;
Coor*& coor = _2d._allRootCoor[index];
if (coor == nullptr)
{
coor = Coor::Create();
coor->_rootIndex = (int)index;
}
return coor;
}
void VK::_create_gfx()
{
for (auto& iter : _gfx._arrVB)
{
iter.Init(this);
}
//------------------------------gfx--------------------------------
// 0.描述符布局
// ubo
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
uboLayoutBinding.pImmutableSamplers = nullptr; // Optional
std::array<VkDescriptorSetLayoutBinding, 1> bindings = {
uboLayoutBinding
};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = (uint32_t)bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(_device, &layoutInfo, nullptr,
&_gfx._descriptorSetLayout) != VK_SUCCESS)
{
log_damage0("创建gfx描述符集合失败!");
return;
}
// 3.管线布局
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1; // Optional
pipelineLayoutInfo.pSetLayouts = &_gfx._descriptorSetLayout; // Optional
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_gfx._pipelineLayout) != VK_SUCCESS)
{
log_damage0("创建gfx管线布局失败!");
return;
}
// 4.统一缓冲
const size_t num = _countFrame * 2; // 3d、2d * 帧数
VkDeviceSize bufferSize = sizeof(VKGfx::UBO);
_gfx._uniformBuffers.resize(num);
_gfx._uniformBuffersMemory.resize(num);
for (size_t i = 0; i < num; i++)
{
CreateBuffer(bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_gfx._uniformBuffers[i], _gfx._uniformBuffersMemory[i]);
}
// 5.描述符池
std::array<VkDescriptorPoolSize, 1> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = (uint32_t)num;
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = (uint32_t)poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = (uint32_t)(poolSizes.size() * num);
if (vkCreateDescriptorPool(_device, &poolInfo, nullptr, &_gfx._descriptorPool) != VK_SUCCESS)
{
log_err0("创建描述符池失败!");
return;
}
// 6.分配描述符(2d和3d需要不同变换)
std::vector<VkDescriptorSetLayout> layouts(num, _gfx._descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _gfx._descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_gfx._descriptorSets.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _gfx._descriptorSets.data()) != VK_SUCCESS)
{
log_err0("分配gfx描述符集失败!");
return;
}
//填充描述符
for (size_t i = 0; i < num; ++i)
{
//ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _gfx._uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(VKGfx::UBO);
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _gfx._descriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
// 顶点缓存
for (VertexBufferGfx& vb : _gfx._arrVB)
{
for (size_t i = 0; i < _countFrame; ++i)
{
vb[i]._num = NUM_GFX_VERTEX;
CreateVertexBufferCPU<VertexGfx>(vb[i]._num,
vb[i]._vertexBuffer, vb[i]._vertexBufferMemory, vb[i]._vertexBufferSize);
}
}
}
void VK::_delete_gfx()
{
for (auto& iter : _gfx._arrVB)
{
iter.Delete(_device);
}
//ub
for (size_t i = 0; i < _countFrame * 2; ++i)
{
vkDestroyBuffer(_device, _gfx._uniformBuffers[i], nullptr);
vkFreeMemory(_device, _gfx._uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorPool(_device, _gfx._descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _gfx._descriptorSetLayout, nullptr);
vkDestroyPipelineLayout(_device, _gfx._pipelineLayout, nullptr);
}
void VK::_create_skybox()
{
_skybox._current = -1;
_create_descriptor_set_layout_skybox();
_create_pipeline_layout_skybox();
size_t num = _countFrame;
// 分配描述符
std::vector<VkDescriptorSetLayout> layouts(num, _skybox._descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_skybox._descriptorSets.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _skybox._descriptorSets.data()) != VK_SUCCESS)
{
log_err0("分配描述符集(skybox)失败!");
return;
}
// 更新描述符
for (size_t i = 0; i < num; ++i)
{
size_t index = 0 * num + i;
// ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(VK::UbObject);
// ubpass
VkDescriptorBufferInfo bufferInfo1{};
bufferInfo1.buffer = _ubPass[i];
bufferInfo1.offset = 0;
bufferInfo1.range = sizeof(UbPass);
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _skybox._descriptorSets[index];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = _skybox._descriptorSets[index];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pBufferInfo = &bufferInfo1;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
// 顶点缓存
std::vector<VertexSkybox> vertices;
Mesh mesh;
mesh.InitBox(2.0f, 2.0f, 2.0f);
mesh.Offset({ -1.0f, -1.0f, -1.0f });
for (auto& iter : mesh.GetVertex())
{
VertexSkybox v;
v._pos = iter;
vertices.push_back(v);
}
CreateVertexBufferGPU<VertexSkybox>(vertices, _skybox._vertexBuffer, _skybox._vertexBufferMemory);
CreateIndexBuffer(mesh.GetIndex(), _skybox._indexBuffer, _skybox._indexBufferMemory);
//
auto& param = Engine::GetParamRef();
if (param._show3D && param._useDefaultSkybox)
{
LoadSkybox("dl/skybox/");
SetSkybox(0);
}
}
void VK::_delete_skybox()
{
// skybox
for (auto& iter : _skybox._vec)
{
iter._texIbl.Delete(_device);
iter._texEnv.Delete(_device);
}
_skybox._texBrdf.Delete(_device);
vkDestroySampler(_device, _skybox._iblSampler, nullptr);
vkDestroySampler(_device, _skybox._envSampler, nullptr);
vkDestroySampler(_device, _skybox._brdfSampler, nullptr);
vkDestroyDescriptorSetLayout(_device, _skybox._descriptorSetLayout, nullptr);
vkDestroyPipelineLayout(_device, _skybox._pipelineLayout, nullptr);
vkDestroyBuffer(_device, _skybox._indexBuffer, nullptr);
vkFreeMemory(_device, _skybox._indexBufferMemory, nullptr);
vkDestroyBuffer(_device, _skybox._vertexBuffer, nullptr);
vkFreeMemory(_device, _skybox._vertexBufferMemory, nullptr);
}
void VK::_create_shadow()
{
_create_render_pass_shadow();
_create_descriptor_set_layout_shadow();
_shadow._layout = _create_pipline_layout_shadow();
_shadow._cascade.resize(NUM_SHADOW_CASCADE);
Texture& tex = _shadow._tex;
CreateImage(SIZE_SHADOW_IMAGE, SIZE_SHADOW_IMAGE, 1,
VK_SAMPLE_COUNT_1_BIT, FORMAT_SHADOW_IMAGE, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // 深度附件,着色器采样
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tex._image, tex._memory, NUM_SHADOW_CASCADE);
// 整个View
{
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = tex._image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.format = FORMAT_SHADOW_IMAGE;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = NUM_SHADOW_CASCADE;
if (vkCreateImageView(_device, &viewInfo, nullptr, &tex._imageView) != VK_SUCCESS)
{
log_err0("创建图像视图失败!");
return;
}
}
for (size_t i = 0; i < NUM_SHADOW_CASCADE; ++i)
{
// 切片View
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = tex._image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
viewInfo.format = FORMAT_SHADOW_IMAGE;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = (uint32_t)i;
viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(_device, &viewInfo, nullptr, &_shadow._cascade[i]._imageView) != VK_SUCCESS)
{
log_err0("创建图像视图1失败!");
return;
}
// 帧缓冲
VkFramebufferCreateInfo fbCI{};
fbCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbCI.renderPass = _shadow._renderPass;
fbCI.attachmentCount = 1;
// 只绑定一个深度附件
fbCI.pAttachments = &_shadow._cascade[i]._imageView;
fbCI.width = SIZE_SHADOW_IMAGE;
fbCI.height = SIZE_SHADOW_IMAGE;
fbCI.layers = 1;
vkCreateFramebuffer(_device, &fbCI, nullptr, &_shadow._cascade[i]._frameBuffer);
}
// 阴影贴图采样器
{
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
// 超过取边缘色
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
// 无需各向异性
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_LESS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_shadow._sampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器(shadow)失败!");
return;
}
}
// 更新描述符
{
// shadow
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
imageInfo.imageView = _shadow._tex._imageView;
imageInfo.sampler = _shadow._sampler;
for (size_t i = 0; i < _descriptorSets.size(); ++i)
{
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSets[i];
descriptorWrites[0].dstBinding = BINDING_INDEX_SHADOW;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
}
void VK::_delete_shadow()
{
for (auto& iter : _shadow._cascade)
{
vkDestroyFramebuffer(_device, iter._frameBuffer, nullptr);
vkDestroyImageView(_device, iter._imageView, nullptr);
}
_shadow._tex.Delete(_device);
vkDestroySampler(_device, _shadow._sampler, nullptr);
for (auto& iter : _shadow._ubCsmBuffer)
vkDestroyBuffer(_device, iter, nullptr);
for (auto& iter : _shadow._ubCsmMemory)
vkFreeMemory(_device, iter, nullptr);
vkDestroyDescriptorSetLayout(_device, _shadow._descriptorSetLayout, nullptr);
vkDestroyPipelineLayout(_device, _shadow._layout, nullptr);
vkDestroyRenderPass(_device, _shadow._renderPass, nullptr);
}
bool VK::_check_gfx_vertex(VertexBufferGfx::Frame& f_old)
{
if (f_old._index >= f_old._num)
{
//
VertexBufferGfx::Frame f;
f._num = f_old._num * 2;
if (f._num < f_old._index)
f._num = Math::AlignPow2((unsigned)f_old._index, 2);
// 创建新f
if (!CreateVertexBufferCPU<VertexGfx>(f._num,
f._vertexBuffer, f._vertexBufferMemory, f._vertexBufferSize))
{
return false;
}
// 新f lock
f.Lock(_device);
f_old.Lock(_device);
// 复制内容
memcpy(f._vertex, f_old._vertex, f_old._index);
// 旧f unlock并释放
f_old.Unlock(_device);
f_old.Delete(_device);
// 设置回变量
f_old._vertexBuffer = f._vertexBuffer;
f_old._vertexBufferMemory = f._vertexBufferMemory;
f_old._vertexBufferSize = f._vertexBufferSize;
f_old._vertex = f._vertex;
f_old._num = f._num;
log_info("gfx顶点扩容至[{}]:{}", _currentFrame, f_old._num);
}
return true;
}
void VK::_create_pipeline_all()
{
_create_pipeline_gfx();
_create_pipeline_2d();
_create_pipeline_3d();
_create_pipeline_bone();
_create_pipeline_skybox();
_create_pipeline_shadow();
}
void VK::_delete_pipeline_all()
{
for (auto& iter : _gfx._vecGraphicsPipeline)
{
vkDestroyPipeline(_device, iter, nullptr);
}
vkDestroyPipeline(_device, _2d._graphicsPipeline, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineTrans, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineEffect, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineGray, nullptr);
vkDestroyPipeline(_device, _graphicsPipeline, nullptr);
vkDestroyPipeline(_device, _graphicsPipelineBone, nullptr);
vkDestroyPipeline(_device, _skybox._graphicsPipeline, nullptr);
vkDestroyPipeline(_device, _shadow._pipeline, nullptr);
vkDestroyPipeline(_device, _shadow._pipelineBone, nullptr);
}
void VK::_create_pipeline_gfx()
{
//1.管线
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer("dl/shader/gfx_vert.spv");
Buffer fragShaderCode = File::GetBuffer("dl/shader/gfx_frag.spv");
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
// 顶点输入状态
auto bindingDescription = VertexGfx::getBindingDescription();
auto attributeDescriptions = VertexGfx::getAttributeDescriptions();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); // Optional
// 顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly0{};
inputAssembly0.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly0.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
inputAssembly0.primitiveRestartEnable = VK_FALSE;
VkPipelineInputAssemblyStateCreateInfo inputAssembly1{};
inputAssembly1.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly1.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
inputAssembly1.primitiveRestartEnable = VK_FALSE;
VkPipelineInputAssemblyStateCreateInfo inputAssembly2{};
inputAssembly2.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly2.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly2.primitiveRestartEnable = VK_FALSE;
// 管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// 光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;//不剔除应该更快 //VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;//与3d不同
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
// 多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;// 必须匹配
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
if (OPEN_SAMPLE_SHADING)
{
multisampling.sampleShadingEnable = VK_TRUE;
// min fraction for sample shading; closer to one is smooth
multisampling.minSampleShading = .2f;
}
// 混合模式
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;//启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;//引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly0;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = _gfx._pipelineLayout;//布局
pipelineInfo.renderPass = _renderPass2D;//渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
// 点图元 顶点着色器需要设置 gl_PointSize
// https://github.com/KhronosGroup/Vulkan-Samples/issues/539
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[0]) != VK_SUCCESS)
{
log_damage0("gfx图形管线0创建失败!");
return;
}
pipelineInfo.pInputAssemblyState = &inputAssembly1;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[1]) != VK_SUCCESS)
{
log_damage0("gfx图形管线1创建失败!");
return;
}
pipelineInfo.pInputAssemblyState = &inputAssembly2;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[2]) != VK_SUCCESS)
{
log_damage0("gfx图形管线2创建失败!");
return;
}
colorBlendAttachment.blendEnable = VK_TRUE;
//相等也必须混合,因为背景可能是不透明物体,在DrawCall里,一定是后画的
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
pipelineInfo.pInputAssemblyState = &inputAssembly0;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[3]) != VK_SUCCESS)
{
log_damage0("gfx图形管线4创建失败!");
return;
}
pipelineInfo.pInputAssemblyState = &inputAssembly1;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[4]) != VK_SUCCESS)
{
log_damage0("gfx图形管线5创建失败!");
return;
}
pipelineInfo.pInputAssemblyState = &inputAssembly2;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_gfx._vecGraphicsPipeline[5]) != VK_SUCCESS)
{
log_damage0("gfx图形管线6创建失败!");
return;
}
// 资源释放
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
vertShaderCode.clear();
fragShaderCode.clear();
}
void VK::_create_pipeline_2d()
{
// 1.管线
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer("dl/shader/2d_vert.spv");
Buffer fragShaderCode = File::GetBuffer("dl/shader/2d_frag.spv");
Buffer fragShaderCodeGray = File::GetBuffer("dl/shader/2d_gray_frag.spv");
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkShaderModule fragShaderModuleGray = CreateShaderModule(fragShaderCodeGray);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfoGray{};
fragShaderStageInfoGray.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfoGray.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfoGray.module = fragShaderModuleGray;
fragShaderStageInfoGray.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
VkPipelineShaderStageCreateInfo shaderStagesGray[] = { vertShaderStageInfo, fragShaderStageInfoGray };
// 顶点输入状态
auto bindingDescription = Vertex2D::getBindingDescription();
auto attributeDescriptions = Vertex2D::getAttributeDescriptions();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); // Optional
// 顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
// 管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// 光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;//不剔除应该更快 //VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;//与3d不同
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
// 多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;// 必须匹配
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
if (OPEN_SAMPLE_SHADING)
{
multisampling.sampleShadingEnable = VK_TRUE;
// min fraction for sample shading; closer to one is smooth
multisampling.minSampleShading = .2f;
}
// 混合模式
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;//启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;//引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = _2d._pipelineLayout;//布局
pipelineInfo.renderPass = _renderPass2D;//渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_2d._graphicsPipeline) != VK_SUCCESS)
{
log_damage0("2d图形管线创建失败!");
return;
}
colorBlendAttachment.blendEnable = VK_TRUE;
//相等也必须混合,因为背景可能是不透明物体,在DrawCall里,一定是后画的
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_2d._graphicsPipelineTrans) != VK_SUCCESS)
{
log_damage0("2d图形管线创建失败!Trans");
return;
}
pipelineInfo.pStages = shaderStagesGray; //引用shader
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_2d._graphicsPipelineGray) != VK_SUCCESS)
{
log_damage0("2d图形管线创建失败!Gray");
return;
}
pipelineInfo.pStages = shaderStages; // 引用shader
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_2d._graphicsPipelineEffect) != VK_SUCCESS)
{
log_damage0("2d图形管线创建失败!Effect");
return;
}
// 资源释放
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, fragShaderModuleGray, nullptr);
vertShaderCode.clear();
fragShaderCode.clear();
fragShaderCodeGray.clear();
}
void VK::_create_pipeline_3d()
{
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer("dl/shader/3d_vert.spv");
Buffer fragShaderCode = File::GetBuffer("dl/shader/3d_frag.spv");
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
//顶点输入状态
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); // Optional
//顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
//管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
//光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
//多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = _param._msaaLevel;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
if (OPEN_SAMPLE_SHADING)
{
multisampling.sampleShadingEnable = VK_TRUE;
// min fraction for sample shading; closer to one is smooth
multisampling.minSampleShading = .2f;
}
//混合模式
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;//启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;//引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = _pipelineLayout;//布局
pipelineInfo.renderPass = _renderPass3D;//渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_graphicsPipeline) != VK_SUCCESS)
{
log_damage0("图形管线创建失败!");
return;
}
//资源释放
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
}
void VK::_create_pipeline_bone()
{
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer("dl/shader/3d_bone_vert.spv");
Buffer fragShaderCode = File::GetBuffer("dl/shader/3d_frag.spv");
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
// 顶点输入状态
auto bindingDescription = VertexBone::getBindingDescription();
auto attributeDescriptions = VertexBone::getAttributeDescriptions();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); // Optional
// 顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
// 管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// 光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
// 多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = _param._msaaLevel;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
if (OPEN_SAMPLE_SHADING)
{
multisampling.sampleShadingEnable = VK_TRUE;
// min fraction for sample shading; closer to one is smooth
multisampling.minSampleShading = .2f;
}
// 混合模式
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;// 启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;// 引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = _pipelineLayoutBone;// 布局
pipelineInfo.renderPass = _renderPass3D;// 渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_graphicsPipelineBone) != VK_SUCCESS)
{
log_damage0("图形管线创建失败!");
return;
}
// 资源释放
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
}
void VK::_create_pipeline_skybox()
{
// 加载shader文件
Buffer vertShaderCode = File::GetBuffer("dl/shader/skybox_vert.spv");
Buffer fragShaderCode = File::GetBuffer("dl/shader/skybox_frag.spv");
// 创建shader模块
VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode);
VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode);
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
// 顶点输入状态
auto bindingDescription = VertexSkybox::getBindingDescription();
auto attributeDescriptions = VertexSkybox::getAttributeDescriptions();
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; // Optional
vertexInputInfo.vertexAttributeDescriptionCount = (uint32_t)attributeDescriptions.size();
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); // Optional
// 顶点装配状态
VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
// 管线动态状态
std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState{};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// 光栅器状态
VkPipelineRasterizationStateCreateInfo rasterizer{};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
// 多重采样状态
VkPipelineMultisampleStateCreateInfo multisampling{};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = _param._msaaLevel;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
if (OPEN_SAMPLE_SHADING)
{
multisampling.sampleShadingEnable = VK_TRUE;
// min fraction for sample shading; closer to one is smooth
multisampling.minSampleShading = .2f;
}
// 混合模式
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;// 启用后会禁用前者
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
// 深度模板状态
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_FALSE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
// 图形管线
VkGraphicsPipelineCreateInfo pipelineInfo{};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;//引用shader
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = _skybox._pipelineLayout;//布局
pipelineInfo.renderPass = _renderPass3D;// 渲染流程
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
pipelineInfo.basePipelineIndex = -1; // Optional
// 深度测试 开 <=
// 深度写入 关
// 关闭剔除
// 关闭混合
if (vkCreateGraphicsPipelines(_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr,
&_skybox._graphicsPipeline) != VK_SUCCESS)
{
log_damage0("图形管线(skybox)创建失败!");
return;
}
// 资源释放
vkDestroyShaderModule(_device, fragShaderModule, nullptr);
vkDestroyShaderModule(_device, vertShaderModule, nullptr);
}
void VK::_create_pipeline_shadow()
{
{
auto bind_desc = Vertex::getBindingDescription();
auto attr_desc = Vertex::getAttributeDescriptions();
_shadow._pipeline = _create_graphics_pipeline_shadow(
"dl/shader/csm_vert.spv",
"dl/shader/csm_frag.spv",
&bind_desc,
attr_desc.data(), attr_desc.size(), _shadow._layout);
}
{
auto bind_desc = VertexBone::getBindingDescription();
auto attr_desc = VertexBone::getAttributeDescriptions();
_shadow._pipelineBone = _create_graphics_pipeline_shadow(
"dl/shader/csm_bone_vert.spv",
"dl/shader/csm_bone_frag.spv",
&bind_desc,
attr_desc.data(), attr_desc.size(), _shadow._layout);
}
}
void VK::ExportTexture(Texture tex, std::string_view path_name)
{
uint32_t width = tex._width;
uint32_t height = tex._height;
bool support_blit = true;
VkFormat format = DL_VK_FORMAT_SRGB_TEXTURE;
// 检查是否支持 blit操作
VkFormatProperties format_props;
vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &format_props);
if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT))
{
log("不支持blit,将使用copy替代!");
support_blit = false;
}
// 检查是否支持 blit到线性image
vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &format_props);
if (!(format_props.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT))
{
log("不支持blit到指定格式,将使用copy替代!");
support_blit = false;
}
// 创建线性布局目标图像
VkImageCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create_info.imageType = VK_IMAGE_TYPE_2D;
create_info.format = format;
create_info.extent.width = width;
create_info.extent.height = height;
create_info.extent.depth = 1;
create_info.arrayLayers = 1;
create_info.mipLevels = 1;
create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create_info.samples = VK_SAMPLE_COUNT_1_BIT;
create_info.tiling = VK_IMAGE_TILING_LINEAR;
create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImage dst_image;
if (vkCreateImage(_device, &create_info, nullptr, &dst_image) != VK_SUCCESS)
{
log_err0("创建dst_image失败!");
return;
}
// 创建图像内存
VkMemoryRequirements memRequirements;
VkMemoryAllocateInfo memAllocInfo{};
VkDeviceMemory dstImageMemory;
vkGetImageMemoryRequirements(_device, dst_image, &memRequirements);
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memRequirements.size;
// 内存本地可见,且可作为复制目标
memAllocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(_device, &memAllocInfo, nullptr, &dstImageMemory) != VK_SUCCESS)
{
log_err0("分配指定内存失败!");
return;
}
if (vkBindImageMemory(_device, dst_image, dstImageMemory, 0) != VK_SUCCESS)
{
log_err0("绑定图像与内存失败!");
return;
}
VkImage src_image = tex._image;
// 将dst_image变为传输目标状态
TransitionImageLayout(dst_image, format,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
// 将src_image变为传输源状态
TransitionImageLayout(src_image, format,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1);
//
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
if (support_blit)
{
VkOffset3D blitSize;
blitSize.x = width;
blitSize.y = height;
blitSize.z = 1;
VkImageBlit imageBlitRegion{};
imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlitRegion.srcSubresource.layerCount = 1;
imageBlitRegion.srcOffsets[1] = blitSize;
imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlitRegion.dstSubresource.layerCount = 1;
imageBlitRegion.dstOffsets[1] = blitSize;
vkCmdBlitImage(
commandBuffer,
src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageBlitRegion,
VK_FILTER_NEAREST);
}
else
{
VkImageCopy imageCopyRegion{};
imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopyRegion.srcSubresource.layerCount = 1;
imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopyRegion.dstSubresource.layerCount = 1;
imageCopyRegion.extent.width = width;
imageCopyRegion.extent.height = height;
imageCopyRegion.extent.depth = 1;
vkCmdCopyImage(
commandBuffer,
src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageCopyRegion);
}
EndSingleTimeCommands(commandBuffer);
//将dst_image变为 生成状态
TransitionImageLayout(dst_image, format,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, 1);
//将src_image变为 初始状态
TransitionImageLayout(src_image, format,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1);
//返回图像布局
VkImageSubresource sub_res{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
VkSubresourceLayout sub_res_layout;
vkGetImageSubresourceLayout(_device, dst_image, &sub_res, &sub_res_layout);
//映射内存
const char* data;
vkMapMemory(_device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
data += sub_res_layout.offset;
Image* image = Img::Create({ width, height }, ColorDef::CYAN);
uint32_t* p = image->GetData();
//复制像素(a通道并未填充,需要自己赋ff)
for (uint32_t y = 0; y < height; y++)
{
uint32_t* row = (uint32_t*)data;
for (uint32_t x = 0; x < width; x++)
{
*p = *row;
++p;
++row;
}
data += sub_res_layout.rowPitch;
}
Img::Save(image, path_name);
delete image;
//清理资源
vkUnmapMemory(_device, dstImageMemory);
vkFreeMemory(_device, dstImageMemory, nullptr);
vkDestroyImage(_device, dst_image, nullptr);
}
void VK::ExportTextureCanvas(std::string_view path)
{
for (auto& iter : _2d._allCanvas)
{
std::string str = fmt::format("{}{}.png", path, iter.first);
ExportTexture(iter.second->_texture, str);
}
}
void VK::GenerateMipmaps(VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels)
{
//检查线性过滤 可用
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(_physicalDevice, imageFormat, &formatProperties);
if (!(formatProperties.optimalTilingFeatures
& VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
{
log_damage0("不支持当前纹理格式的线性过滤!");
return;
}
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.image = image;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.subresourceRange.levelCount = 1;
int32_t mipWidth = texWidth;
int32_t mipHeight = texHeight;
for (uint32_t i = 1; i < mipLevels; ++i)
{
barrier.subresourceRange.baseMipLevel = i - 1;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
0, nullptr,
0, nullptr,
1, &barrier);
VkImageBlit blit{};
blit.srcOffsets[0] = { 0, 0, 0 };
blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.srcSubresource.mipLevel = i - 1;
blit.srcSubresource.baseArrayLayer = 0;
blit.srcSubresource.layerCount = 1;
blit.dstOffsets[0] = { 0, 0, 0 };
blit.dstOffsets[1] = {
mipWidth > 1 ? mipWidth / 2 : 1,
mipHeight > 1 ? mipHeight / 2 : 1,
1 };
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.dstSubresource.mipLevel = i;
blit.dstSubresource.baseArrayLayer = 0;
blit.dstSubresource.layerCount = 1;
vkCmdBlitImage(commandBuffer,
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit,
VK_FILTER_LINEAR);
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
0, nullptr,
0, nullptr,
1, &barrier);
if (mipWidth > 1) mipWidth /= 2;
if (mipHeight > 1) mipHeight /= 2;
}
barrier.subresourceRange.baseMipLevel = mipLevels - 1;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
0, nullptr,
0, nullptr,
1, &barrier);
EndSingleTimeCommands(commandBuffer);
}
void VK::_create_depth_resources()
{
VkFormat depthFormat = FindDepthFormat();
CreateImage(_extentSwapChain.width, _extentSwapChain.height, 1, VK_SAMPLE_COUNT_1_BIT,
depthFormat, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _depthImage, _depthImageMemory);
_depthImageView = CreateImageView(_depthImage, depthFormat,
VK_IMAGE_ASPECT_DEPTH_BIT, 1);
TransitionImageLayout(_depthImage, depthFormat,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1);
}
void VK::_create_color_resources()
{
VkFormat colorFormat = _formatSwapChainImage;
CreateImage(_extentSwapChain.width, _extentSwapChain.height, 1, _param._msaaLevel, colorFormat,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, _colorImage, _colorImageMemory);
_colorImageView = CreateImageView(_colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
bool VK::CreateRenderTargetReal(size_t i, VKRenderTarget& rt)
{
{
VkFormat colorFormat = _formatSwapChainImage;
CreateImage(_extentSwapChain.width, _extentSwapChain.height, 1, _param._msaaLevel, colorFormat,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, rt._texColor._image, rt._texColor._memory);
rt._texColor._imageView = CreateImageView(rt._texColor._image, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
{
VkFormat depthFormat = FindDepthFormat();
CreateImage(_extentSwapChain.width, _extentSwapChain.height, 1, _param._msaaLevel,
depthFormat, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, rt._texDepth._image, rt._texDepth._memory);
rt._texDepth._imageView = CreateImageView(rt._texDepth._image, depthFormat,
VK_IMAGE_ASPECT_DEPTH_BIT, 1);
TransitionImageLayout(rt._texDepth._image, depthFormat,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1);
}
{
VkFormat colorFormat = _formatSwapChainImage;
CreateImage(_extentSwapChain.width, _extentSwapChain.height, 1, VK_SAMPLE_COUNT_1_BIT, colorFormat,
VK_IMAGE_TILING_OPTIMAL,
// translate标记不可写入到显存,sampled表示可以被后续作为shader资源
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | // 导出纹理使用
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, rt._texColorOut._image, rt._texColorOut._memory);
rt._texColorOut._imageView = CreateImageView(rt._texColorOut._image, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
rt._texColorOut._width = _extentSwapChain.width;
rt._texColorOut._height = _extentSwapChain.height;
}
{
std::array<VkImageView, 3> attachments = {
rt._texColor._imageView,
rt._texDepth._imageView,
rt._texColorOut._imageView
};
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = _renderPass3D; // 渲染流程
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
framebufferInfo.pAttachments = attachments.data();
framebufferInfo.width = _extentSwapChain.width;
framebufferInfo.height = _extentSwapChain.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(_device, &framebufferInfo, nullptr, &rt._frameBuffer) != VK_SUCCESS)
{
log_damage0("创建帧缓冲区(RenderTarget)失败!");
return false;
}
}
return true;
}
VkSampleCountFlagBits VK::GetMaxUsableSampleCount()
{
VkPhysicalDeviceProperties physicalDeviceProperties;
vkGetPhysicalDeviceProperties(_physicalDevice, &physicalDeviceProperties);
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts
& physicalDeviceProperties.limits.framebufferDepthSampleCounts;
if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
return VK_SAMPLE_COUNT_1_BIT;
}
size_t VK::LoadSkybox(std::string_view path)
{
Skybox::Instance sky;
// sh
{
std::string str = File::GetString(path + "sh.txt");
std::vector<std::string_view> vec;
vec = String::SplitViewNoEmpty(str, '\n');
if (vec.size() != 9)
{
log_err0("解析sh参数失败!");
return -1;
}
for (size_t i = 0; i < vec.size(); ++i)
{
std::string_view sub = String::Range(vec[i], '(', ')');
Position3 pos = String::toPosition<3>(sub);
sky._sh[i] = toLonger(pos, 1.0f);
}
}
// env
{
_create_texture_ktx(path + "skybox.ktx", sky._texEnv);
}
// ibl
{
_create_texture_ktx(path + "ibl.ktx", sky._texIbl);
}
size_t id = _skybox._vec.size();
_skybox._vec.push_back(sky);
return id;
}
void VK::SetSkybox(size_t i)
{
if (i >= _skybox._vec.size())
{
log_warn("天空盒设置失败,下标越界:{}/{}", i, _skybox._vec.size());
return;
}
vkQueueWaitIdle(_graphicsQueue);
_skybox._current = i;
Skybox::Instance& sky = _skybox._vec[_skybox._current];
//
_pass._sh = sky._sh;
// 更新描述符
{
// ibl (正常管线)
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = sky._texIbl._imageView;
imageInfo.sampler = _skybox._iblSampler;
for (size_t i = 0; i < _descriptorSets.size(); ++i)
{
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _descriptorSets[i];
descriptorWrites[0].dstBinding = BINDING_INDEX_IBL;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
{
// env (skybox管线)
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = sky._texEnv._imageView;
imageInfo.sampler = _skybox._envSampler;
for (size_t i = 0; i < _skybox._descriptorSets.size(); ++i)
{
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _skybox._descriptorSets[i];
descriptorWrites[0].dstBinding = 2;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
}
size_t VK::CreateRenderTarget()
{
size_t i = _allRenderTarget.size();
if (i >= CANVAS_ID_RENDER_TARGET_MAX)
{
log_err("RenderTarget数量超过上限:{}/{}", i, CANVAS_ID_RENDER_TARGET_MAX);
return -1;
}
VKRenderTarget rt;
CreateRenderTargetReal(i, rt);
CreateCanvasRenderTarget(i, rt);
_allRenderTarget.push_back(rt);
return i;
}
VK::~VK()
{
for (auto& iter : _allRenderTarget)
{
iter.Delete(_device);
}
_delete_pipeline_all();
_delete_gfx();
_delete_2d();
_delete_skybox();
_delete_shadow();
// 3d
for (auto& iter : _allMulModel)
{
for (Model* model : iter)
{
DeleteModel(model);
}
}
// texture
vkDestroySampler(_device, _standardSampler, nullptr);
vkDestroySampler(_device, _pointSampler, nullptr);
for (auto& iter : _allTexture3D)
{
iter.Delete(_device);
}
// ub bone
for (size_t i = 0; i < _countFrame * NUM_MAX_BONE; i++)
{
vkDestroyBuffer(_device, _ubBone[i], nullptr);
vkFreeMemory(_device, _ubBoneMemory[i], nullptr);
}
// ubPass
for (size_t i = 0; i < _countFrame; ++i)
{
vkDestroyBuffer(_device, _ubPass[i], nullptr);
vkFreeMemory(_device, _ubPassMemory[i], nullptr);
}
// ubMaterial
for (size_t i = 0; i < NUM_MAX_MATERIAL; ++i)
{
vkDestroyBuffer(_device, _ubMaterial[i], nullptr);
vkFreeMemory(_device, _ubMaterialMemory[i], nullptr);
}
// ub
for (size_t i = 0; i < _uniformBuffersMemory.size(); ++i)
{
vkDestroyBuffer(_device, _uniformBuffers[i], nullptr);
vkFreeMemory(_device, _uniformBuffersMemory[i], nullptr);
}
// descriptor
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayout, nullptr);
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayoutBone, nullptr);
vkDestroyDescriptorSetLayout(_device, _descriptorSetLayoutTex, nullptr);
vkDestroyDescriptorPool(_device, _descriptorPool, nullptr);
// fence
for (size_t i = 0; i < _countFrame; ++i)
{
vkDestroySemaphore(_device, _allSemaphoreImageAvailable[i], nullptr);
vkDestroySemaphore(_device, _allSemaphoreRenderFinished[i], nullptr);
vkDestroyFence(_device, _allFenceInFlight[i], nullptr);
}
vkDestroyCommandPool(_device, _commandPoolUpload, nullptr);
vkDestroyCommandPool(_device, _commandPool, nullptr);
// pipeline
vkDestroyPipelineLayout(_device, _pipelineLayoutBone, nullptr);
vkDestroyPipelineLayout(_device, _pipelineLayout, nullptr);
vkDestroyRenderPass(_device, _renderPass2D, nullptr);
vkDestroyRenderPass(_device, _renderPass3D, nullptr);
vkDestroySurfaceKHR(_instance, _surface, nullptr);
vkDestroyDevice(_device, nullptr);
if (ENABLE_VALIDATION_LAYERS)
DestroyDebugUtilsMessengerEXT(_instance, _debugMessenger, nullptr);
vkDestroyInstance(_instance, nullptr);
}
size_t VK::CreateTexture(std::string_view path_name, bool srgb)
{
std::string str = std::string{ path_name };
auto iter = _mapPath2Texture.find(str);
if (iter != _mapPath2Texture.end())
{
return iter->second;
}
Image* image = Img::Create(str);
if (!image)
return 0;
size_t ret = CreateTextureReal(image, srgb, true);
if (ret != 0)
_mapPath2Texture[str] = ret;
return ret;
}
void VK::CreateCanvas(size_t id, Texture tex, std::string_view path_tex_full)
{
auto iter = _2d._allCanvas.find(id);
if (iter != _2d._allCanvas.end())
{
log_damage("Canvas已存在:{}", id);
return;
}
Canvas* canvas = new Canvas(this);
canvas->_id = id;
canvas->_texture = tex;
canvas->_pathTextureFull = path_tex_full;
if (!path_tex_full.empty())
canvas->_textureState = 1;
for (size_t i = 0; i < _countFrame; ++i)
{
canvas->_numVertex[i] = NUM_START_2D_VERTEX;
CreateVertexBufferCPU<Vertex2D>(canvas->_numVertex[i],
canvas->_vertexBuffer[i], canvas->_vertexBufferMemory[i], canvas->_vertexBufferSize[i]);
}
_2d._allCanvas[id] = canvas;
UpdateCanvasDescriptor(canvas);
}
void VK::CreateCanvasImage(size_t tex_id, const std::array<Image*, NUM_MIPMAP_2D>& vec_image)
{
CreateCanvas(CANVAS_ID_RENDER_TARGET_MAX + tex_id, CreateTexture2D(vec_image), "");
}
void VK::CreateCanvasImageKtx(size_t tex_id, std::string_view path_name, std::string_view path_tex_full)
{
Texture tex;
_create_texture_ktx(path_name, tex);
CreateCanvas((int)(CANVAS_ID_RENDER_TARGET_MAX + tex_id), tex, path_tex_full);
}
void VK::CreateCanvasRenderTarget(size_t rt_id, VKRenderTarget& rt)
{
CreateCanvas(rt_id, rt._texColorOut, "");
}
void VK::UpdateCanvasRenderTarget(size_t rt_id, VKRenderTarget& rt)
{
Canvas* canvas = GetCanvas(rt_id);
assert(canvas);
canvas->_texture.Delete(_device);
canvas->_texture = rt._texColorOut;
//填充描述符
size_t id = rt_id;
//for (size_t i = 0; i < _countFrame; ++i)
//{
//size_t index = id * _countFrame + i;
// 纹理
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = canvas->_texture._imageView;
imageInfo.sampler = VK_NULL_HANDLE;
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _2d._descriptorSets1[id];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
//}
}
void VK::UpdateCanvasDescriptor(Canvas* canvas)
{
size_t id = canvas->_id;
//填充描述符
//for (size_t i = 0; i < _countFrame; ++i)
//{
//size_t index = id * _countFrame + i;
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = canvas->_texture._imageView;
imageInfo.sampler = VK_NULL_HANDLE;
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _2d._descriptorSets1[id];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
//}
}
VK::Canvas* VK::GetCanvas(size_t id)
{
auto iter = _2d._allCanvas.find(id);
if (iter == _2d._allCanvas.end())
return nullptr;
return iter->second;
}
dl::VK::Canvas* VK::GetCanvasByTexture(size_t tex_id)
{
return GetCanvas(CANVAS_ID_RENDER_TARGET_MAX + tex_id);
}
dl::VK::Canvas* VK::GetCanvasByRenderTarget(size_t rt_id)
{
return GetCanvas(rt_id);
}
Texture VK::CreateTexture2D(const std::array<Image*, NUM_MIPMAP_2D>& vec_image)
{
for(auto& iter : vec_image)
assert(iter);
Texture tex;
// mipmap数
tex._mipLevel = NUM_MIPMAP_2D;
std::array<Size, NUM_MIPMAP_2D> vec_size; // 图像大小
std::array<VkBuffer, NUM_MIPMAP_2D> vec_buffer_stag; // 暂存缓冲
std::array<VkDeviceMemory, NUM_MIPMAP_2D> vec_buffer_stag_mem; // 暂存缓冲内存
for (size_t i = 0; i < NUM_MIPMAP_2D; ++i)
{
vec_size[i] = vec_image[i]->GetSize();
// 创建
VkDeviceSize imageSize = vec_image[i]->GetSizeByte();
CreateBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vec_buffer_stag[i], vec_buffer_stag_mem[i]);
void* data;
// 拷贝
vkMapMemory(_device, vec_buffer_stag_mem[i], 0, imageSize, 0, &data);
memcpy(data, vec_image[i]->GetBuffer(), static_cast<size_t>(imageSize));
vkUnmapMemory(_device, vec_buffer_stag_mem[i]);
}
VkFormat format = DL_VK_FORMAT_SRGB_TEXTURE;
// 创建显存图像
// VK_IMAGE_USAGE_TRANSFER_SRC_BIT 用于导出图像
CreateImage((uint32_t)vec_size[0][0], (uint32_t)vec_size[0][1], tex._mipLevel, VK_SAMPLE_COUNT_1_BIT,
format,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
tex._image, tex._memory);
// 转换状态 为 复制目标
TransitionImageLayout(tex._image, format,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
tex._mipLevel);
// 暂存缓冲 -> 显存缓冲
CopyBufferToImageMulti(vec_buffer_stag, tex._image, vec_size);
// 转换状态 为 着色器资源
TransitionImageLayout(tex._image, format,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, tex._mipLevel);
// 释放
for (size_t i = 0; i < NUM_MIPMAP_2D; ++i)
{
vkDestroyBuffer(_device, vec_buffer_stag[i], nullptr);
vkFreeMemory(_device, vec_buffer_stag_mem[i], nullptr);
}
// 创建视图
tex._imageView = CreateImageView(tex._image,
format, VK_IMAGE_ASPECT_COLOR_BIT, tex._mipLevel);
tex._width = (uint32_t)vec_size[0][0];
tex._height = (uint32_t)vec_size[0][1];
return tex;
}
void VK::UpdateTexture2D(Texture tex, const PointU& xy, Image* image, const RectU& rect, bool mipmap)
{
// mipmap数
tex._mipLevel = mipmap ? NUM_MIPMAP_2D : VK_SAMPLE_COUNT_1_BIT;
size_t count = tex._mipLevel;
// 生成图像组
struct ImageMipmap
{
Image* _img;
PointU _xy;
RectU _rect;
};
std::array<ImageMipmap, NUM_MIPMAP_2D> vec_image;
vec_image[0]._img = image;
vec_image[0]._xy = xy;
vec_image[0]._rect = rect;
for (size_t i = 1; i < count; ++i)
{
ImageMipmap& last = vec_image[i - 1];
Size size = last._img->GetSize() / 2u;
Every::ClampFloor(size, 1u);
vec_image[i]._img = Img::Resize(image, size);
vec_image[i]._xy = toSize(toPosition(last._xy) * 0.5f);
vec_image[i]._rect = toSize(toPosition(last._rect) * 0.5f);
}
std::array<Size, NUM_MIPMAP_2D> vec_size; // 图像大小
std::array<VkBuffer, NUM_MIPMAP_2D> vec_buffer_stag; // 暂存缓冲
std::array<VkDeviceMemory, NUM_MIPMAP_2D> vec_buffer_stag_mem; // 暂存缓冲内存
for (size_t i = 0; i < count; ++i)
{
vec_size[i] = vec_image[i]._img->GetSize();
// 创建
VkDeviceSize imageSize = vec_image[i]._img->GetSizeByte();
CreateBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vec_buffer_stag[i], vec_buffer_stag_mem[i]);
void* data;
// 拷贝
vkMapMemory(_device, vec_buffer_stag_mem[i], 0, imageSize, 0, &data);
memcpy(data, vec_image[i]._img->GetBuffer(), static_cast<size_t>(imageSize));
vkUnmapMemory(_device, vec_buffer_stag_mem[i]);
}
VkFormat format = DL_VK_FORMAT_SRGB_TEXTURE;
//转换状态 为 复制目标
TransitionImageLayout(tex._image, format,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
tex._mipLevel);
//暂存缓冲 -> 显存缓冲
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
//指定区域
VkBufferImageCopy region{};
//偏移计算如下
//address of(x, y, z) =
// region->bufferOffset +
// (((z * imageHeight) + y) * rowLength + x) * elementSize;
for (size_t i = 0; i < count; ++i)
{
Size size = vec_image[i]._img->GetSize();
Size rect_size = Align::GetSize(vec_image[i]._rect);
Every::ClampFloor(rect_size, 1u);
PointU rect_lt = Align::GetLT(vec_image[i]._rect);
region.bufferOffset = (rect_lt[1] * size[0] + rect_lt[0]) * sizeof(uint32_t);
region.bufferRowLength = (uint32_t)size[0];
region.bufferImageHeight = (uint32_t)size[1];
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = (uint32_t)i;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { (int32_t)vec_image[i]._xy[0], (int32_t)vec_image[i]._xy[1], 0 };
region.imageExtent = { (uint32_t)rect_size[0], (uint32_t)rect_size[1], 1 };
vkCmdCopyBufferToImage(commandBuffer, vec_buffer_stag[i], tex._image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
}
EndSingleTimeCommands(commandBuffer);
//转换状态 为 着色器资源
TransitionImageLayout(tex._image, format,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, tex._mipLevel);
// 释放
for (size_t i = 0; i < count; ++i)
{
vkDestroyBuffer(_device, vec_buffer_stag[i], nullptr);
vkFreeMemory(_device, vec_buffer_stag_mem[i], nullptr);
}
for (size_t i = 1; i < count; ++i)
{
delete vec_image[i]._img;
}
}
void VK::ScreenShot(std::string_view path_name)
{
uint32_t width = _extentSwapChain.width;
uint32_t height = _extentSwapChain.height;
bool support_blit = true;
// 检查是否支持 blit操作
VkFormatProperties format_props;
vkGetPhysicalDeviceFormatProperties(_physicalDevice, _formatSwapChainImage, &format_props);
if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT))
{
log("不支持blit,将使用copy替代!");
support_blit = false;
}
VkFormat format = DL_VK_FORMAT_SRGB_TEXTURE;
// 检查是否支持 blit到 指定格式
vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &format_props);
if (!(format_props.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT))
{
log("不支持blit到线性布局image,将使用copy替代!");
support_blit = false;
}
// 当前交换链图像
VkImage src_image = _allImageSwapChain[_currentFrame];
// 创建线性布局目标图像
VkImageCreateInfo create_info{};
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
create_info.imageType = VK_IMAGE_TYPE_2D;
create_info.format = format;
create_info.extent.width = width;
create_info.extent.height = height;
create_info.extent.depth = 1;
create_info.arrayLayers = 1;
create_info.mipLevels = 1;
create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
create_info.samples = VK_SAMPLE_COUNT_1_BIT;
create_info.tiling = VK_IMAGE_TILING_LINEAR;
create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
VkImage dst_image;
if (vkCreateImage(_device, &create_info, nullptr, &dst_image) != VK_SUCCESS)
{
log_err0("创建dst_image失败!");
return;
}
// 创建内存内存
VkMemoryRequirements memRequirements;
VkMemoryAllocateInfo memAllocInfo{};
VkDeviceMemory dstImageMemory;
vkGetImageMemoryRequirements(_device, dst_image, &memRequirements);
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memRequirements.size;
// 内存本地可见,且可作为复制目标
memAllocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(_device, &memAllocInfo, nullptr, &dstImageMemory) != VK_SUCCESS)
{
log_err0("分配指定内存失败!");
return;
}
if (vkBindImageMemory(_device, dst_image, dstImageMemory, 0) != VK_SUCCESS)
{
log_err0("绑定图像与内存失败!");
return;
}
// 将dst_image变为传输目标状态
TransitionImageLayout(dst_image, format,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
// 将src_image变为传输源状态
TransitionImageLayout(src_image, _formatSwapChainImage,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1);
//
VkCommandBuffer commandBuffer = BeginSingleTimeCommands();
if (support_blit)
{
VkOffset3D blitSize;
blitSize.x = width;
blitSize.y = height;
blitSize.z = 1;
VkImageBlit imageBlitRegion{};
imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlitRegion.srcSubresource.layerCount = 1;
imageBlitRegion.srcOffsets[1] = blitSize;
imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlitRegion.dstSubresource.layerCount = 1;
imageBlitRegion.dstOffsets[1] = blitSize;
vkCmdBlitImage(
commandBuffer,
src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageBlitRegion,
VK_FILTER_NEAREST);
}
else
{
VkImageCopy imageCopyRegion{};
imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopyRegion.srcSubresource.layerCount = 1;
imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCopyRegion.dstSubresource.layerCount = 1;
imageCopyRegion.extent.width = width;
imageCopyRegion.extent.height = height;
imageCopyRegion.extent.depth = 1;
vkCmdCopyImage(
commandBuffer,
src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dst_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&imageCopyRegion);
}
EndSingleTimeCommands(commandBuffer);
// 将dst_image变为 生成状态
TransitionImageLayout(dst_image, format,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, 1);
// 将src_image变为 初始状态
TransitionImageLayout(src_image, _formatSwapChainImage,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1);
// 返回图像布局
VkImageSubresource sub_res{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
VkSubresourceLayout sub_res_layout;
vkGetImageSubresourceLayout(_device, dst_image, &sub_res, &sub_res_layout);
// 映射内存
const char* data;
vkMapMemory(_device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
data += sub_res_layout.offset;
// 使用交换链支持的颜色格式
bool color_bgr = false;
if (!support_blit)
{
std::vector<VkFormat> formatsBGR = { VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SNORM };
color_bgr = (std::find(formatsBGR.begin(), formatsBGR.end(), _formatSwapChainImage) != formatsBGR.end());
}
Image* image = Img::Create({ width, height }, ColorDef::CYAN);
uint32_t* p = image->GetData();
//复制像素(a通道并未填充,需要自己赋ff)
for (uint32_t y = 0; y < height; y++)
{
uint32_t* row = (uint32_t*)data;
for (uint32_t x = 0; x < width; x++)
{
if (color_bgr)
{//颜色转换
uint32_t abgr = ARGB::ToABGR(*row);
*p = 0xff000000 | (abgr << 8 >> 8);
}
else
{
*p = *row;
}
++p;
++row;
}
data += sub_res_layout.rowPitch;
}
Img::Save(image, path_name);
delete image;
//清理资源
vkUnmapMemory(_device, dstImageMemory);
vkFreeMemory(_device, dstImageMemory, nullptr);
vkDestroyImage(_device, dst_image, nullptr);
}
void VK::Update()
{
// 等待当前帧完成
vkWaitForFences(_device, 1, &_allFenceInFlight[_currentFrame], VK_TRUE, UINT64_MAX);
// gfx
for (size_t i = 0; i < NUM_GFX;++i)
{
auto& vec = _gfx._allVertex[i];
VertexBufferGfx::Frame& f = _gfx._arrVB[i][_currentFrame];
f._index = vec.size();
if(f._index == 0)
continue;
if (_check_gfx_vertex(f))
{
f.Lock(_device);
memcpy(f._vertex, vec.data(), f._index * sizeof(VertexGfx));
f.Unlock(_device);
}
}
//
for (size_t i = 0; i < NUM_GFX; ++i)
{
_2d._renderInfo._numGfx[i] = _gfx._allVertex[i].size();
}
for(auto& iter : _gfx._allVertex)
iter.clear();
// 2d
_2d._renderInfo._numSprite = 0;
_2d._renderInfo._numSpriteTranslucent = 0;
_2d._vecDc.clear();
_2d._vecDcTrans.clear();
unsigned tkc = g_time->GetFrameTkc();
// 画布逻辑,更新顶点和cbo
// 半透明需要排序,后面生成dc
// 生成dc,并按z排序
std::multimap<float, DrawCall> map_dc_translucent;
for (auto& iter : _2d._allCanvas)
{
Canvas*& canvas = iter.second;
if (canvas->_allSprite.empty() && canvas->_allSpriteTrans.empty())
{
canvas->TryRelase(this, tkc);
continue;
}
else
{
canvas->_tkcUsed = tkc;
canvas->TryLoad(this);
}
if (canvas->_allSprite.size() > NUM_MAX_2D_SPRITE)
{
log_warn("精灵数超过上限:{}", NUM_MAX_2D_SPRITE);
canvas->_allSprite.resize(NUM_MAX_2D_SPRITE);
canvas->_allSpriteTrans.resize(0);
}
else
{
size_t remain = NUM_MAX_2D_SPRITE - canvas->_allSprite.size();
if (canvas->_allSpriteTrans.size() > remain)
{
log_warn("精灵数超过上限:{}", NUM_MAX_2D_SPRITE);
canvas->_allSpriteTrans.resize(remain);
}
}
_2d._renderInfo._numSprite += canvas->_allSprite.size();
_2d._renderInfo._numSpriteTranslucent += canvas->_allSpriteTrans.size();
//0.顶点缓冲区大小检查
const size_t num_vertex_need = (canvas->_allSprite.size()
+ canvas->_allSpriteTrans.size()) * 4;
if (num_vertex_need > canvas->_numVertex[_currentFrame])
{// 重建当前frame(等待GPU完成)
vkDestroyBuffer(_device, canvas->_vertexBuffer[_currentFrame], nullptr);
vkFreeMemory(_device, canvas->_vertexBufferMemory[_currentFrame], nullptr);
canvas->_numVertex[_currentFrame] = num_vertex_need * 2;
CreateVertexBufferCPU<Vertex2D>(
canvas->_numVertex[_currentFrame], canvas->_vertexBuffer[_currentFrame],
canvas->_vertexBufferMemory[_currentFrame], canvas->_vertexBufferSize[_currentFrame]);
}
//1.拆分所有精灵到不同drawCall
//(由于后render的在后面,所以反过来添加,这样同order先Render的就不能通过z测试)
_2d._vecDcList.Reset();
for (int i = (int)canvas->_allSprite.size() - 1; i >= 0; --i)
{
Sprite* spr = canvas->_allSprite[i];
spr->_bRender = false;
DrawCallList dcl;
DrawCall& dc = dcl._dc;
dc._canvas = canvas;
dc._rootCoor = spr->GetCoor() ? spr->GetCoor()->GetRoot() : nullptr;
dc._scissorRect = spr->_scissorRect;
dc._viewport = spr->_viewport;
dc._sampler = spr->_sampler;
dc._blend = spr->_blend;
DrawCallList* dcl_x = _2d._vecDcList.Find(dcl);
if (dcl_x == nullptr)
{
dcl._listSpr.push_back(spr);
_2d._vecDcList.Add(dcl);
}
else
{
dcl_x->_listSpr.push_back(spr);
}
}
Vertex2D* vertex;// 顶点内存
vkMapMemory(_device, canvas->_vertexBufferMemory[_currentFrame], 0,
canvas->_vertexBufferSize[_currentFrame], 0, (void**)&vertex);
//2.添加精灵
size_t j = 0;// 写入顶点位置,每个精灵4个
auto fn_add_spr_vertex = [&](Sprite* spr)
{
for (size_t i = 0; i != 4; ++i)
{
Position pos = spr->_quad.Get(i);
// 坐标变换
if (spr->_coor)
{
pos = spr->_coor->ThisToRoot(pos);
}
// 取整像素
if (spr->_bRoundPixel)
{
Every::Round(pos);
}
Vertex2D& v = vertex[j + i];
v._pos[0] = (float)pos[0];
v._pos[1] = (float)pos[1];
v._pos[2] = spr->_order;
if (spr->_blend == Sprite::Blend::EFFECT)
{// blend模式的 alpha需要作用到颜色上才能实现透明
v._color = spr->_col[i];
v._color[0] *= v._color[3];
v._color[1] *= v._color[3];
v._color[2] *= v._color[3];
}
else
v._color = spr->_col[i];
// 亮度
if (spr->_bright != 1.0f)
{// 可超过1.0
v._color[0] *= spr->_bright;
v._color[1] *= spr->_bright;
v._color[2] *= spr->_bright;
}
v._uv = spr->_uv[i];
}
j += 4;
};
// 3.按DrawCall写入内存,记录顶点位置
for (DrawCallList*& iter : _2d._vecDcList)
{
DrawCall dc = iter->_dc; // 复制一份
dc._beg = j;
for (auto& iter1 : iter->_listSpr)
{
fn_add_spr_vertex(iter1);
}
dc._end = j;
_2d._vecDc.push_back(dc);
}
// 4.生成按z的drawCall(意味着z值不同不能合并,目前为止。只有z值相同,且Dc相同才能合并)
// 半透精灵 z测试是 LESS_EQUAL,所以 后Render的 后添加
_2d._vecDcListZ.Reset();
for (size_t i = 0; i < canvas->_allSpriteTrans.size(); ++i)
{
Sprite* spr = canvas->_allSpriteTrans[i];
spr->_bRender = false;
DrawCallZ& dcz = _2d._tempDcListZ;
dcz._z = spr->GetOrder();
dcz._dcl._listSpr.clear();
DrawCall& dc = dcz._dcl._dc;
dc._canvas = canvas;
dc._rootCoor = spr->GetCoor() ? spr->GetCoor()->GetRoot() : nullptr;
dc._scissorRect = spr->_scissorRect;
dc._viewport = spr->_viewport;
dc._sampler = spr->_sampler;
dc._blend = spr->_blend;
DrawCallZ* dcz_x = _2d._vecDcListZ.Find(dcz);
if (dcz_x == nullptr)
{
dcz._dcl._listSpr.push_back(spr);
_2d._vecDcListZ.Add(dcz);
}
else
{
dcz_x->_dcl._listSpr.push_back(spr);
}
}
//5.写入顶点
for (DrawCallZ*& iter : _2d._vecDcListZ)
{
DrawCallList dcl = iter->_dcl;//复制一份
dcl._dc._beg = j;
for (auto& iter1 : dcl._listSpr)
{
fn_add_spr_vertex(iter1);
}
dcl._dc._end = j;
map_dc_translucent.insert({ iter->_z, dcl._dc });
}
vkUnmapMemory(_device, canvas->_vertexBufferMemory[_currentFrame]);
canvas->_allSprite.clear();
canvas->_allSpriteTrans.clear();
}
//合并连续 且画布相同的项
DrawCall* pre = nullptr;
//由于按z升序,所以反过来添加 ,避免z测试
for (auto iter = map_dc_translucent.rbegin(); iter != map_dc_translucent.rend(); ++iter)
{
auto& dc = iter->second;
if (pre
&& dc == *pre
&& (dc._beg == pre->_end))
{//是连续的
pre->_end = dc._end;
}
else
{
_2d._vecDcTrans.push_back(dc);
pre = &_2d._vecDcTrans.back();
}
}
_2d._renderInfo._numDrawCall = _2d._vecDc.size();
_2d._renderInfo._numDrawCallTranslucent = _2d._vecDcTrans.size();
// 更新cbo
for (size_t i = 0; i < NUM_MAX_ROOT_COOR; ++i)
{
Coor* coor = _2d._allRootCoor[i];
if (coor)
{
Matrix4& mat = _2d._allRootCoorMat[i];
Matrix4 mat_t = Mat::CreateTranslation(toLonger(coor->GetPosition()));
Matrix4 mat_r = Mat::CreateRotation(Position3{0, 0, 1}, coor->GetRotate());
Matrix4 mat_s = Mat::CreateScaling(toLonger(coor->GetScale(), 1.0f));
mat = mat_t * mat_s * mat_r;
}
}
// 更新统一常量ubo
VK2D::UBO ubo{};
switch (g_system->GetWindowDirection())
{
case WindowDirection::UP:
{
Matrix4 mat_proj = Mat::CreateOrthogonal(
0.0f, 0.0f,
(Float)_extentSwapChain.width, (Float)_extentSwapChain.height,
0.0f, 1.0f);
ubo._viewProj = mat_proj;
}
break;
case WindowDirection::RIGHT:
{
// TODO
/*Matrix4 mat_view = Mat::CreateLookTo(
Position3{ 0.0f, 0.0f, 0.0f },
Position3{ 0.0f, 0.0f, 1.0f },
Position3{ -1.0f, 0.0f, 0.0f });
Matrix4 mat_proj = Mat::CreateOrthogonal(
-(Float)_extentSwapChain.width, 0.0f,
0.0f, (Float)_extentSwapChain.height,
0.0f, 1.0f);
ubo._viewProj = mat_proj * mat_view;
Mat::ApplyTranslation(ubo._viewProj,
Position3{ -(Float)_extentSwapChain.height, 0.0f, 0.0f });*/
}
break;
case WindowDirection::DOWN:
case WindowDirection::LEFT:
default:
assert(0); // TODO
break;
}
if (USE_MAPPED_2D_UBO)
{
memcpy(_2d._uniformBuffersMapped[_currentFrame], &ubo, sizeof(ubo));
}
else
{
{
void* data;
vkMapMemory(_device, _2d._uniformBuffersMemory[_currentFrame], 0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(_device, _2d._uniformBuffersMemory[_currentFrame]);
}
// 2d gfx
{
void* data;
vkMapMemory(_device, _gfx._uniformBuffersMemory[_currentFrame + _countFrame],
0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(_device, _gfx._uniformBuffersMemory[_currentFrame + _countFrame]);
}
}
}
}
#endif