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