Files
dl_old/dl/vk/dl_vk.cpp
T
2026-05-27 15:06:50 +08:00

6206 lines
206 KiB
C++
Raw 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"
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;
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_graphics_pipeline();
_create_graphics_pipeline_bone();
_create_command_pool();
_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();
}
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;
_msaaSamples = 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)
{
//队列族
QueueFamilyIndices indices = _find_queue_families(device);
//扩展
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 indices.IsComplete()
&& extensionsSupported
&& swapChainAdequate
&& supportedFeatures.samplerAnisotropy;
}
QueueFamilyIndices VK::_find_queue_families(VkPhysicalDevice device)
{
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
//至少一个支持VK_QUEUE_GRAPHICS_BIT
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
indices._graphicsFamily = i;
}
//
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, _surface, &presentSupport);
if (presentSupport) {
indices._presentFamily = i;
}
//
if (indices.IsComplete())
{
break;
}
i++;
}
return indices;
}
void VK::_create_logical_device()
{
QueueFamilyIndices indices = _find_queue_families(_physicalDevice);
VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices._graphicsFamily.value();
queueCreateInfo.queueCount = 1;
//对列优先级
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;
//物理设备特性
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.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
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 = {
indices._graphicsFamily.value(), indices._presentFamily.value()
};
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, indices._graphicsFamily.value(), 0, &_graphicsQueue);
//从device获得呈现队列
vkGetDeviceQueue(_device, indices._presentFamily.value(), 0, &_presentQueue);
}
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() };
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;
}
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()
{
// color
VkAttachmentDescription colorAttachment{};
colorAttachment.format = _formatSwapChainImage;
colorAttachment.samples = _msaaSamples;
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_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorAttachmentRef{};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// depth
VkAttachmentDescription depthAttachment{};
depthAttachment.format = FindDepthFormat();
depthAttachment.samples = _msaaSamples;
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;
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_PRESENT_SRC_KHR;
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, &_renderPass) != VK_SUCCESS)
{
log_damage0("渲染流程创建失败!");
return;
}
}
void VK::_create_graphics_pipeline()
{
// 加载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 = _msaaSamples;
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
// 推送常量区
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;
}
// 深度模板状态
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 = _renderPass;//渲染流程
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_graphics_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 = _msaaSamples;
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
// 管线布局
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;
}
// 深度模板状态
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 = _renderPass;//渲染流程
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_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;
}
}
VK::Pipeline VK::_create_graphics_pipeline_shadow(std::string_view vs, std::string_view ps,
VkVertexInputBindingDescription* bind_desc, VkVertexInputAttributeDescription* attr_desc, size_t num_attr)
{
Pipeline 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;
// 推送常量区
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._layout) != VK_SUCCESS)
{
log_damage0("创建管线布局(shadow)失败!");
return ret;
}
// 深度模板状态
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 = ret._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._pipe) != 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 = NUM_MAX_FRAME_IN_FLIGHT;
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(NUM_MAX_FRAME_IN_FLIGHT);
_shadow._ubCsmMemory.resize(NUM_MAX_FRAME_IN_FLIGHT);
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 < NUM_MAX_FRAME_IN_FLIGHT; ++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 * NUM_MAX_FRAME_IN_FLIGHT + 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_graphics_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 = _msaaSamples;
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
// 推送常量区
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;
}
// 深度模板状态
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 = _renderPass;// 渲染流程
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_frame_buffer()
{
_allFrameBufferSwapChain.resize(_allImageViewSwapChain.size());
//
for (size_t i = 0; i < _allImageViewSwapChain.size(); i++)
{
std::array<VkImageView, 3> attachments = {
_colorImageView,
_depthImageView,
_allImageViewSwapChain[i]
};
VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = _renderPass;//应用绘制流程
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()
{
QueueFamilyIndices queueFamilyIndices = _find_queue_families(_physicalDevice);
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = queueFamilyIndices._graphicsFamily.value();
if (vkCreateCommandPool(_device, &poolInfo, nullptr, &_commandPool) != VK_SUCCESS)
{
log_damage0("创建命令池失败!");
return;
}
}
void VK::_create_command_buffer()
{
_allCommandBuffer.resize(NUM_MAX_FRAME_IN_FLIGHT);
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)NUM_MAX_FRAME_IN_FLIGHT;
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;
}
// 阴影贴图生成
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);
}
// 渲染流程Begin
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = _renderPass;
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);
// 设置视口与裁剪
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;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = _extentSwapChain;
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
//--------------------------------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);
}
}
_curPushConstant = 1;
//--------------------------------2d---------------------------------------
// 单个dc
VkPipeline pipeline_last = 0;
_2d._renderInfo._numSwitchPso = 0;
auto fn_render_dc = [&](const std::vector<DrawCall>& list_dc, bool is_trans)
{
for (const DrawCall& dc : list_dc)
{
// 切换管线
VkPipeline pipeline;
if (dc._blend == 1)
pipeline = _2d._graphicsPipelineEffect;
else if (dc._blend == 2)
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 * NUM_MAX_FRAME_IN_FLIGHT
+ _currentFrame);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_2d._pipelineLayout, 0, 1, &_2d._descriptorSets[offset_tex], 0, nullptr);
// 推送常量(变换)
size_t id_coor = dc._rootCoor ? dc._rootCoor->GetRootIndex() : 0;
vkCmdPushConstants(command_buffer, _2d._pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(VK2D::CBO), &_2d._allCBO[id_coor]);
// 绑定顶点缓冲区
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())
{
// 绑定管线
//vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _2d._graphicsPipeline);
// 绑定索引缓冲
vkCmdBindIndexBuffer(command_buffer, _2d._indexBuffer, 0, VK_INDEX_TYPE_UINT32);
fn_render_dc(_2d._vecDc, false);
}
//--------------------gfx 不透明----------------
// 设置视口
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// 设置裁剪
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
// 绑定顶点缓冲区
for (size_t i = 0; i < NUM_GFX_HALF; ++i)
{
size_t index = _currentFrame;
if(i >= NUM_GFX_QUAD)
index += NUM_MAX_FRAME_IN_FLIGHT;
// 绑定管线
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._vecGraphicsPipeline[i % NUM_GFX_HALF]);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._pipelineLayout, 0, 1, &_gfx._descriptorSets[index], 0, nullptr);
VertexBuffer& vb = _gfx._arrVB[i];
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);
}
//--------------------2d 透明----------------------
if (!_2d._vecDcTrans.empty())
{
// 绑定管线
//vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, _2d._graphicsPipelineTrans);
if (_2d._vecDc.empty())
{// 前面没绑,这里绑一次
// 绑定索引缓冲
vkCmdBindIndexBuffer(command_buffer, _2d._indexBuffer, 0, VK_INDEX_TYPE_UINT32);
}
fn_render_dc(_2d._vecDcTrans, true);
}
//--------------------gfx 透明----------------
// 设置视口
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// 设置裁剪
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
//绑定顶点缓冲区
for (size_t i = NUM_GFX_HALF; i < NUM_GFX; ++i)
{
size_t index = _currentFrame;
if (i >= NUM_GFX_HALF + NUM_GFX_QUAD)
index += NUM_MAX_FRAME_IN_FLIGHT;
//绑定管线
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._vecGraphicsPipeline[NUM_GFX_QUAD + (i - NUM_GFX_HALF) % 3]);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
_gfx._pipelineLayout, 0, 1, &_gfx._descriptorSets[index], 0, nullptr);
VertexBuffer& vb = _gfx._arrVB[i];
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);
}
//结束
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 auto TIME_OUT = std::numeric_limits<uint64_t>::max();
vkWaitForFences(_device, 1, &_allFenceInFlight[_currentFrame], VK_TRUE, TIME_OUT);
vkResetFences(_device, 1, &_allFenceInFlight[_currentFrame]);
// 获得交换链图像(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;
}
//next:
//更新统一缓冲
_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;
}
}
// if (!paused) {
// if ((animate) && (models.scene.animations.size() > 0)) {
// animationTimer += frameTimer;
// if (animationTimer > models.scene.animations[animationIndex].end) {
// animationTimer -= models.scene.animations[animationIndex].end;
// }
// models.scene.updateAnimation(animationIndex, animationTimer);
// updateMeshDataBuffer(frameIndex);
// }
// updateParams();
// }
_currentFrame = (_currentFrame + 1) % NUM_MAX_FRAME_IN_FLIGHT;
}
void VK::_create_sync_objects()
{
_allSemaphoreImageAvailable.resize(NUM_MAX_FRAME_IN_FLIGHT);
_allSemaphoreRenderFinished.resize(NUM_MAX_FRAME_IN_FLIGHT);
_allFenceInFlight.resize(NUM_MAX_FRAME_IN_FLIGHT);
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 < NUM_MAX_FRAME_IN_FLIGHT; ++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;
}
}
}
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();
#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();
}
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(NUM_MAX_FRAME_IN_FLIGHT);
_uniformBuffersMemory.resize(NUM_MAX_FRAME_IN_FLIGHT);
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; 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(NUM_MAX_FRAME_IN_FLIGHT);
_ubPassMemory.resize(NUM_MAX_FRAME_IN_FLIGHT);
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; 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);
constexpr size_t num = NUM_MAX_FRAME_IN_FLIGHT * 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;
/*ktx_size_t offset;
ktx_uint8_t* image;
ktx_uint32_t level, layer, faceSlice;*/
ktxVulkanDeviceInfo vdi;
ktxVulkanTexture texture;
// 构造Device数据
result = ktxVulkanDeviceInfo_Construct(&vdi, _physicalDevice, _device,
_graphicsQueue, _commandPool, nullptr);
if (result != KTX_SUCCESS)
{
log_err("ktx解析失败(info):{}", path);
return;
}
result = ktxTexture_CreateFromMemory((ktx_uint8_t*)buf.data(), buf.size(),
KTX_TEXTURE_CREATE_NO_FLAGS,
&kTexture);
if (result != KTX_SUCCESS)
{
log_err("ktx解析失败(create):{}", path);
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("ktx[{}]: \nmip {}, layer {}, depth {}\nw {}, h {}\nformat {}",
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 * NUM_MAX_FRAME_IN_FLIGHT);
uint32_t num_all = 0;
// set 0
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = (num * 3 +
NUM_MAX_FRAME_IN_FLIGHT +// shadow
NUM_MAX_FRAME_IN_FLIGHT)*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 * NUM_MAX_FRAME_IN_FLIGHT);
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 * NUM_MAX_FRAME_IN_FLIGHT;
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 = NUM_MAX_FRAME_IN_FLIGHT * 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 < NUM_MAX_FRAME_IN_FLIGHT; i++)
{
size_t index = j * NUM_MAX_FRAME_IN_FLIGHT + 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 < NUM_MAX_FRAME_IN_FLIGHT; i++)
{
size_t index = j * NUM_MAX_FRAME_IN_FLIGHT + 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._pipe : &_shadow._pipelineBone._pipe;
pipe_layout = !has_skin ? &_shadow._pipeline._layout : &_shadow._pipelineBone._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 * NUM_MAX_FRAME_IN_FLIGHT
+ _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 * NUM_MAX_FRAME_IN_FLIGHT
+ _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.描述符布局
// 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 texLayoutBinding0{};
texLayoutBinding0.binding = 1;
texLayoutBinding0.descriptorCount = 1;
texLayoutBinding0.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
texLayoutBinding0.pImmutableSamplers = nullptr;
texLayoutBinding0.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
uboLayoutBinding, texLayoutBinding0
};
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,
&_2d._descriptorSetLayout) != VK_SUCCESS)
{
log_damage0("创建描述符集合失败!");
return;
}
// 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 = _msaaSamples;//必须匹配
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
// 推送常量区
VkPushConstantRange pushConstantRange{};
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRange.offset = 0;
pushConstantRange.size = sizeof(VK2D::CBO);
// 管线布局
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1; // Optional
pipelineLayoutInfo.pSetLayouts = &_2d._descriptorSetLayout; // Optional
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
if (vkCreatePipelineLayout(_device, &pipelineLayoutInfo, nullptr, &_2d._pipelineLayout) != VK_SUCCESS)
{
log_damage0("创建2d管线布局失败!");
return;
}
// 深度模板状态
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 = _renderPass;//渲染流程
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();
// 3.纹理采样器
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_NEAREST;// VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_NEAREST;
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;
samplerInfo.maxLod = NUM_MIPMAP_2D;
if (vkCreateSampler(_device, &samplerInfo, nullptr, &_2d._textureSampler) != VK_SUCCESS)
{
log_damage0("创建纹理采样器失败!");
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(NUM_MAX_FRAME_IN_FLIGHT);
_2d._uniformBuffersMemory.resize(NUM_MAX_FRAME_IN_FLIGHT);
_2d._uniformBuffersMapped.resize(NUM_MAX_FRAME_IN_FLIGHT);
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; 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, 2> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = (uint32_t)NUM_MAX_DESCRIPTOR_POOL_2D;
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = (uint32_t)NUM_MAX_DESCRIPTOR_POOL_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)(poolSizes.size() * NUM_MAX_DESCRIPTOR_POOL_2D);
if (vkCreateDescriptorPool(_device, &poolInfo, nullptr, &_2d._descriptorPool) != VK_SUCCESS)
{
log_err0("创建描述符池失败!");
return;
}
//6.分配描述符
size_t num = NUM_MAX_DRAW_CALL_2D * NUM_MAX_FRAME_IN_FLIGHT;
std::vector<VkDescriptorSetLayout> layouts(num, _2d._descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _2d._descriptorPool;
allocInfo.descriptorSetCount = (uint32_t)num;
allocInfo.pSetLayouts = layouts.data();
_2d._descriptorSets.resize(num);
if (vkAllocateDescriptorSets(_device, &allocInfo, _2d._descriptorSets.data()) != VK_SUCCESS)
{
log_err0("分配2d描述符集失败!");
return;
}
//
for (auto& iter : _2d._allRootCoor)
{
iter = nullptr;
}
for (auto& iter : _2d._allCBO)
{
iter._model.Identity();
}
}
void VK::_delete_2d()
{
for (auto& iter : _2d._allRootCoor)
{
if(iter)
iter->_rootIndex = -1;
delete iter;
}
vkDestroySampler(_device, _2d._textureSampler, nullptr);
for (auto& iter : _2d._allCanvas)
{
iter->Delete(_device);
delete iter;
}
//索引缓冲
vkDestroyBuffer(_device, _2d._indexBuffer, nullptr);
vkFreeMemory(_device, _2d._indexBufferMemory, nullptr);
//ub
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; i++)
{
vkDestroyBuffer(_device, _2d._uniformBuffers[i], nullptr);
vkFreeMemory(_device, _2d._uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorPool(_device, _2d._descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _2d._descriptorSetLayout, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipeline, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineTrans, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineEffect, nullptr);
vkDestroyPipeline(_device, _2d._graphicsPipelineGray, 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()
{
//------------------------------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;
}
//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 = _msaaSamples;//必须匹配
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
// 管线布局
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;
}
// 深度模板状态
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 = _renderPass;//渲染流程
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();
// 4.统一缓冲
constexpr size_t num = NUM_MAX_FRAME_IN_FLIGHT * 2;
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)
{
size_t index = 0 * num + i;
//ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _gfx._uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(VK2D::UBO);
std::array<VkWriteDescriptorSet, 1> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _gfx._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;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
// 顶点缓存
for (VertexBuffer& vb : _gfx._arrVB)
{
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; ++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 < NUM_MAX_FRAME_IN_FLIGHT * 2; ++i)
{
vkDestroyBuffer(_device, _gfx._uniformBuffers[i], nullptr);
vkFreeMemory(_device, _gfx._uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorPool(_device, _gfx._descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(_device, _gfx._descriptorSetLayout, nullptr);
for (auto& iter : _gfx._vecGraphicsPipeline)
{
vkDestroyPipeline(_device, iter, nullptr);
}
vkDestroyPipelineLayout(_device, _gfx._pipelineLayout, nullptr);
}
void VK::_create_skybox()
{
_skybox._current = -1;
_create_descriptor_set_layout_skybox();
_create_graphics_pipeline_skybox();
size_t num = NUM_MAX_FRAME_IN_FLIGHT;
// 分配描述符
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);
//
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);
vkDestroyPipeline(_device, _skybox._graphicsPipeline, 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();
{
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());
}
{
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._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);
_shadow._pipeline.Delete(_device);
_shadow._pipelineBone.Delete(_device);
vkDestroyRenderPass(_device, _shadow._renderPass, nullptr);
}
bool VK::_check_gfx_vertex(VertexBuffer& vb_old)
{
VertexBuffer::Frame& f_old = vb_old[_currentFrame];
if (f_old._index >= f_old._num)
{
//
VertexBuffer::Frame f;
f._num = f_old._num * 2;
constexpr auto TIME_OUT = std::numeric_limits<uint64_t>::max();
vkWaitForFences(_device, 1, &_allFenceInFlight[_currentFrame], VK_TRUE, TIME_OUT);
// 创建新f
if (!CreateVertexBufferCPU<VertexGfx>(f._num,
f._vertexBuffer, f._vertexBufferMemory, f._vertexBufferSize))
{
return false;
}
// 新f lock
vkMapMemory(_device, f._vertexBufferMemory, 0,
f._vertexBufferSize, 0, (void**)&f._vertex);
// 复制内容
memcpy(f._vertex, f_old._vertex, f_old._index);
// 旧f unlock并释放
vkUnmapMemory(_device, f_old._vertexBufferMemory);
vkDestroyBuffer(_device, f_old._vertexBuffer, nullptr);
vkFreeMemory(_device, f_old._vertexBufferMemory, nullptr);
// 设置回变量
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顶点扩容至:{}", f_old._num);
}
return true;
}
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::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, _msaaSamples,
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);
}
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;
}
_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);
}
}
}
VK::~VK()
{
_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 < NUM_MAX_FRAME_IN_FLIGHT * NUM_MAX_BONE; i++)
{
vkDestroyBuffer(_device, _ubBone[i], nullptr);
vkFreeMemory(_device, _ubBoneMemory[i], nullptr);
}
// ubPass
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; ++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 < NUM_MAX_FRAME_IN_FLIGHT; ++i)
{
vkDestroySemaphore(_device, _allSemaphoreImageAvailable[i], nullptr);
vkDestroySemaphore(_device, _allSemaphoreRenderFinished[i], nullptr);
vkDestroyFence(_device, _allFenceInFlight[i], nullptr);
}
vkDestroyCommandPool(_device, _commandPool, nullptr);
// pipeline
vkDestroyPipeline(_device, _graphicsPipelineBone, nullptr);
vkDestroyPipelineLayout(_device, _pipelineLayoutBone, nullptr);
vkDestroyPipeline(_device, _graphicsPipeline, nullptr);
vkDestroyPipelineLayout(_device, _pipelineLayout, nullptr);
vkDestroyRenderPass(_device, _renderPass, 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, const std::array<Image*, NUM_MIPMAP_2D>& vec_image)
{
assert(id == _2d._allCanvas.size());
Canvas* canvas = new Canvas;
canvas->_id = id;
canvas->_texture = CreateTexture2D(vec_image);
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; ++i)
{
canvas->_numVertex[i] = NUM_START_2D_VERTEX;
CreateVertexBufferCPU<Vertex2D>(canvas->_numVertex[i],
canvas->_vertexBuffer[i], canvas->_vertexBufferMemory[i], canvas->_vertexBufferSize[i]);
}
_2d._allCanvas.push_back(canvas);
//填充描述符
for (size_t i = 0; i < NUM_MAX_FRAME_IN_FLIGHT; ++i)
{
size_t index = id * NUM_MAX_FRAME_IN_FLIGHT + i;
// ubo
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = _2d._uniformBuffers[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(VK2D::UBO);
// 纹理
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = canvas->_texture._imageView;
imageInfo.sampler = _2d._textureSampler;
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = _2d._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 = _2d._descriptorSets[index];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(_device,
(uint32_t)descriptorWrites.size(), descriptorWrites.data(),
0, nullptr);
}
}
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)
{
//mipmap数
tex._mipLevel = NUM_MIPMAP_2D;
// 生成图像组
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 < vec_image.size(); ++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 < NUM_MIPMAP_2D; ++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 < vec_buffer_stag.size(); ++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 < NUM_MIPMAP_2D; ++i)
{
vkDestroyBuffer(_device, vec_buffer_stag[i], nullptr);
vkFreeMemory(_device, vec_buffer_stag_mem[i], nullptr);
}
for (size_t i = 1; i < vec_image.size(); ++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()
{
_2d._renderInfo._numSprite = 0;
_2d._renderInfo._numSpriteTranslucent = 0;
_2d._vecDc.clear();
_2d._vecDcTrans.clear();
//画布逻辑,更新顶点和cbo
//半透明需要排序,后面生成dc
//生成dc,并按z排序
std::multimap<float, DrawCall> map_dc_translucent;
for (Canvas*& canvas : _2d._allCanvas)
{
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完成)
constexpr auto TIME_OUT = std::numeric_limits<uint64_t>::max();
vkWaitForFences(_device, 1, &_allFenceInFlight[_currentFrame], VK_TRUE, TIME_OUT);
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 == 1)
{// 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)
{
VK2D::CBO& cbo = _2d._allCBO[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));
cbo._model = 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 + NUM_MAX_FRAME_IN_FLIGHT],
0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(_device, _gfx._uniformBuffersMemory[_currentFrame + NUM_MAX_FRAME_IN_FLIGHT]);
}
}
//
for (size_t i = 0; i < NUM_GFX; ++i)
{
_2d._renderInfo._numGfx[i] = _gfx._arrVB[i][_currentFrame]._index;
}
}
}
#endif