Files
face_sdk/vulkan/FaceApp.cpp
T
2025-12-20 22:34:23 +08:00

1524 lines
48 KiB
C++

#include "FaceApp.h"
#include "hardcode_data.h"
#include "lodepng.h"
#include <sstream>
#include <queue>
#include <vector>
#include <mutex>
FaceApp* FaceApp::faceIns = nullptr;
FaceApp::FaceApp(/* args */)
{
faceIns = this;
}
FaceApp::~FaceApp()
{
if (worker_.joinable()) {
worker_.join();
}
}
void ReceiveFacePoint(float* pos, int pointCount, int width, int height)
{
FaceApp* self = FaceApp::Get();
if (self != nullptr)
{
FaceApp::Get()->update_face_vertex_buffer(pos, pointCount);
}
}
// 定义帧数据结构
struct FrameData {
uint8_t* data;
int width;
int height;
int rowStride;
size_t dataSize;
FrameData(uint8_t* d, int w, int h, int rs, size_t ds)
: data(nullptr), width(w), height(h), rowStride(rs), dataSize(ds) {
// 深拷贝数据
if (d && ds > 0) {
data = new uint8_t[dataSize];
memcpy(data, d, dataSize);
}
}
~FrameData() {
if (data) {
delete[] data;
data = nullptr;
}
}
// 禁止拷贝构造和赋值(使用移动语义)
FrameData(const FrameData&) = delete;
FrameData& operator=(const FrameData&) = delete;
// 移动构造
FrameData(FrameData&& other) noexcept
: data(other.data), width(other.width), height(other.height),
rowStride(other.rowStride), dataSize(other.dataSize) {
other.data = nullptr;
}
// 移动赋值
FrameData& operator=(FrameData&& other) noexcept {
if (this != &other) {
if (data) delete[] data;
data = other.data;
width = other.width;
height = other.height;
rowStride = other.rowStride;
dataSize = other.dataSize;
other.data = nullptr;
}
return *this;
}
};
// 全局队列和互斥锁
std::queue<FrameData> frameQueue;
std::mutex queueMutex;
const int MAX_QUEUE_SIZE = 4;
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize)
{
if (!FaceApp::Get()->isInited()) {
return;
}
std::lock_guard<std::mutex> lock(queueMutex);
// 添加新帧数据到队列
frameQueue.emplace(data, width, height, rowStride, dataSize);
// 如果队列大小达到阈值,开始处理最旧的一帧
if (frameQueue.size() >= MAX_QUEUE_SIZE) {
Texture& tex_bg = FaceApp::Get()->tex_bg;
FrameData& oldestFrame = frameQueue.front();
FaceApp::Get()->processWithVulkan(
oldestFrame.data,
oldestFrame.width,
oldestFrame.height,
oldestFrame.rowStride,
oldestFrame.dataSize,
tex_bg,
false,
FaceApp::Get()->commandPool,
"data_from_camera"
);
frameQueue.pop();
}
}
bool FaceApp::LoadOBJ(const std::string& filename,
std::vector<TextureLoadingVertexStructure>& vertices,
std::vector<uint32_t>& indices) {
// 临时存储从OBJ文件读取的原始数据
std::vector<float> temp_positions;
std::vector<float> temp_texcoords;
std::vector<float> temp_normals;
// 用于处理顶点索引
std::vector<int> vertexIndices, uvIndices, normalIndices;
std::vector<char> data = readFile(filename);
// 将 vector<char> 转换为以 null 结尾的字符串(安全做法)
std::string content(data.begin(), data.end());
std::istringstream iss(content); // 用字符串创建字符串流
std::string line;
while (std::getline(iss, line)) {
// 跳过空行和注释行
if (line.empty() || line[0] == '#') {
continue;
}
std::istringstream iss(line);
std::string type;
iss >> type;
if (type == "v") { // 顶点位置
float x, y, z;
iss >> x >> y >> z;
temp_positions.push_back(x);
temp_positions.push_back(y);
temp_positions.push_back(z);
}
else if (type == "vt") { // 纹理坐标
float u, v;
iss >> u >> v;
temp_texcoords.push_back(u);
temp_texcoords.push_back(1 - v);
}
else if (type == "vn") { // 法线
float nx, ny, nz;
iss >> nx >> ny >> nz;
temp_normals.push_back(nx);
temp_normals.push_back(ny);
temp_normals.push_back(nz);
}
else if (type == "f") { // 面(三角形)
std::string vertex1, vertex2, vertex3;
iss >> vertex1 >> vertex2 >> vertex3;
// 处理每个顶点的索引
for (const std::string& vertex : { vertex1, vertex2, vertex3 }) {
std::istringstream viss(vertex);
std::string v, vt, vn;
// 解析顶点索引格式:v/vt/vn 或 v//vn 或 v
std::getline(viss, v, '/');
std::getline(viss, vt, '/');
std::getline(viss, vn, '/');
int posIndex = std::stoi(v) - 1; // OBJ索引从1开始
int texIndex = -1, normIndex = -1;
if (!vt.empty()) texIndex = std::stoi(vt) - 1;
if (!vn.empty()) normIndex = std::stoi(vn) - 1;
vertexIndices.push_back(posIndex);
uvIndices.push_back(texIndex);
normalIndices.push_back(normIndex);
}
}
}
// 创建顶点数据
vertices.clear();
indices.clear();
// 用于去重的哈希映射
std::map<std::string, uint32_t> vertexMap;
for (size_t i = 0; i < vertexIndices.size(); i++) {
int posIndex = vertexIndices[i];
int texIndex = uvIndices[i];
int normIndex = normalIndices[i];
// 创建唯一标识符
std::string vertexKey = std::to_string(posIndex) + "/" +
std::to_string(texIndex) + "/" +
std::to_string(normIndex);
// 检查是否已经存在相同的顶点
if (vertexMap.find(vertexKey) != vertexMap.end()) {
// 使用现有顶点的索引
indices.push_back(vertexMap[vertexKey]);
}
else {
// 创建新顶点
TextureLoadingVertexStructure vertex;
// 设置位置
if (posIndex >= 0 && posIndex * 3 + 2 < temp_positions.size()) {
vertex.pos[0] = temp_positions[posIndex * 3];
vertex.pos[1] = temp_positions[posIndex * 3 + 1];
vertex.pos[2] = temp_positions[posIndex * 3 + 2];
}
else {
vertex.pos[0] = vertex.pos[1] = vertex.pos[2] = 0.0f;
}
// 设置纹理坐标
if (texIndex >= 0 && texIndex * 2 + 1 < temp_texcoords.size()) {
vertex.uv[0] = temp_texcoords[texIndex * 2];
vertex.uv[1] = temp_texcoords[texIndex * 2 + 1];
}
else {
vertex.uv[0] = vertex.uv[1] = 0.0f;
}
// 设置法线
if (normIndex >= 0 && normIndex * 3 + 2 < temp_normals.size()) {
vertex.normal[0] = temp_normals[normIndex * 3];
vertex.normal[1] = temp_normals[normIndex * 3 + 1];
vertex.normal[2] = temp_normals[normIndex * 3 + 2];
}
else {
vertex.normal[0] = vertex.normal[1] = 0.0f;
vertex.normal[2] = 1.0f; // 默认法线
}
// 添加新顶点并记录索引
uint32_t newIndex = static_cast<uint32_t>(vertices.size());
vertices.push_back(vertex);
indices.push_back(newIndex);
obj_vertices_map[newIndex] = posIndex;
vertexMap[vertexKey] = newIndex;
}
}
return true;
}
void FaceApp::create_face_pipelines()
{
VkPipelineInputAssemblyStateCreateInfo input_assembly_state{};
input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly_state.flags = 0;
input_assembly_state.primitiveRestartEnable = VK_FALSE;
VkPipelineRasterizationStateCreateInfo rasterization_state{};
rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
rasterization_state.cullMode = VK_CULL_MODE_NONE;
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterization_state.flags = 0;
rasterization_state.depthClampEnable = VK_FALSE;
rasterization_state.lineWidth = 1.0f;
rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT;
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.blendEnable = VK_TRUE;
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT;
// 常用的Alpha混合公式
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_ONE_MINUS_SRC_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.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
// Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {};
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil_state.depthTestEnable = VK_TRUE;
depth_stencil_state.depthWriteEnable = VK_TRUE;
depth_stencil_state.depthCompareOp = VK_COMPARE_OP_GREATER;
depth_stencil_state.front = depth_stencil_state.back;
depth_stencil_state.back.compareOp = VK_COMPARE_OP_ALWAYS;
VkPipelineViewportStateCreateInfo viewport_state{};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.scissorCount = 1;
viewport_state.flags = 0;
VkPipelineMultisampleStateCreateInfo multisample_state{};
multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisample_state.flags = 0;
// 动态定义视口和剪裁,暂时用不到
//std::vector<VkDynamicState> dynamic_state_enables = {
// VK_DYNAMIC_STATE_VIEWPORT,
// VK_DYNAMIC_STATE_SCISSOR };
//VkPipelineDynamicStateCreateInfo dynamic_state{};
//dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
//dynamic_state.pDynamicStates = dynamic_state_enables.data();
//dynamic_state.dynamicStateCount = static_cast<uint32_t>(dynamic_state_enables.size());
//dynamic_state.flags = 0;
// 视口状态
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swapChainExtent.width;
viewport.height = (float)swapChainExtent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = swapChainExtent;
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
std::vector<char> vertShaderCode;
std::vector<char> fragShaderCode;
if (kThick)
{
vertShaderCode = readFile("shaders/texture_thick.vert.spv");
fragShaderCode = readFile("shaders/texture_thick.frag.spv");
}
else
{
vertShaderCode = readFile("shaders/texture.vert.spv");
fragShaderCode = readFile("shaders/texture.frag.spv");
}
VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(this->device, 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 shader_stages[] = { vertShaderStageInfo, fragShaderStageInfo };
// Vertex bindings and attributes
std::vector<VkVertexInputBindingDescription> vertex_input_bindings{};;
VkVertexInputBindingDescription vertex_input_binding_description{};
vertex_input_binding_description.binding = 0;
vertex_input_binding_description.stride = sizeof(TextureLoadingVertexStructure);
vertex_input_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vertex_input_bindings.push_back(vertex_input_binding_description);
std::vector<VkVertexInputAttributeDescription> vertex_input_attributes{};
VkVertexInputAttributeDescription viaPos{};
viaPos.location = 0;
viaPos.binding = 0;
viaPos.format = VK_FORMAT_R32G32B32_SFLOAT;
viaPos.offset = offsetof(TextureLoadingVertexStructure, pos);
vertex_input_attributes.push_back(viaPos);
VkVertexInputAttributeDescription viaUv{};
viaUv.location = 1;
viaUv.binding = 0;
viaUv.format = VK_FORMAT_R32G32_SFLOAT;
viaUv.offset = offsetof(TextureLoadingVertexStructure, uv);
vertex_input_attributes.push_back(viaUv);
VkVertexInputAttributeDescription viaNormal{};
viaNormal.location = 2;
viaNormal.binding = 0;
viaNormal.format = VK_FORMAT_R32G32B32_SFLOAT;
viaNormal.offset = offsetof(TextureLoadingVertexStructure, normal);
vertex_input_attributes.push_back(viaNormal);
VkPipelineVertexInputStateCreateInfo vertex_input_state{};
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input_state.vertexBindingDescriptionCount = static_cast<uint32_t>(vertex_input_bindings.size());
vertex_input_state.pVertexBindingDescriptions = vertex_input_bindings.data();
vertex_input_state.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertex_input_attributes.size());
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes.data();
VkGraphicsPipelineCreateInfo pipeline_create_info{};
pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_create_info.layout = m_pipelineLayout;
pipeline_create_info.renderPass = renderPass;
pipeline_create_info.flags = 0;
pipeline_create_info.basePipelineIndex = -1;
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_create_info.pVertexInputState = &vertex_input_state;
pipeline_create_info.pInputAssemblyState = &input_assembly_state;
pipeline_create_info.pRasterizationState = &rasterization_state;
pipeline_create_info.pColorBlendState = &colorBlending; //&color_blend_state;
pipeline_create_info.pMultisampleState = &multisample_state;
pipeline_create_info.pViewportState = &viewport_state;
pipeline_create_info.pDepthStencilState = &depth_stencil_state;
//pipeline_create_info.pDynamicState = &dynamic_state;
pipeline_create_info.pViewportState = &viewportState;
pipeline_create_info.stageCount = 2;
pipeline_create_info.pStages = shader_stages;
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &m_graphicsPipeline));
// 销毁着色器模块
vkDestroyShaderModule(device, fragShaderModule, nullptr);
vkDestroyShaderModule(device, vertShaderModule, nullptr);
}
void FaceApp::setup_descriptor_set_layout()
{
VkDescriptorSetLayoutBinding set_layout_binding_vertex{};
set_layout_binding_vertex.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
set_layout_binding_vertex.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
set_layout_binding_vertex.binding = 0;
set_layout_binding_vertex.descriptorCount = 1;
VkDescriptorSetLayoutBinding set_layout_binding_fragment{};
set_layout_binding_fragment.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
set_layout_binding_fragment.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
set_layout_binding_fragment.binding = 1;
set_layout_binding_fragment.descriptorCount = 1;
if (kThick)
{
// 添加第二个纹理绑定点
VkDescriptorSetLayoutBinding set_layout_binding_fragment1{};
set_layout_binding_fragment1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
set_layout_binding_fragment1.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
set_layout_binding_fragment1.binding = 2;
set_layout_binding_fragment1.descriptorCount = 1;
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings{ set_layout_binding_vertex , set_layout_binding_fragment, set_layout_binding_fragment1 };
VkDescriptorSetLayoutCreateInfo descriptor_layout{};
descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptor_layout.pBindings = set_layout_bindings.data();
descriptor_layout.bindingCount = static_cast<uint32_t>(set_layout_bindings.size());
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout));
}
else
{
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings{ set_layout_binding_vertex , set_layout_binding_fragment };
VkDescriptorSetLayoutCreateInfo descriptor_layout{};
descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptor_layout.pBindings = set_layout_bindings.data();
descriptor_layout.bindingCount = static_cast<uint32_t>(set_layout_bindings.size());
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout));
}
VkPipelineLayoutCreateInfo pipeline_layout_create_info{};
pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_create_info.setLayoutCount = 1;
pipeline_layout_create_info.pSetLayouts = &m_descriptorSetLayout;
//VkPushConstantRange pushConstantRange{};
//pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
//pushConstantRange.offset = 0;
//pushConstantRange.size = sizeof(float);
//pipeline_layout_create_info.pushConstantRangeCount = 1;
//pipeline_layout_create_info.pPushConstantRanges = &pushConstantRange;
VkPushConstantRange pushConstantRanges[1];
pushConstantRanges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT| VK_SHADER_STAGE_FRAGMENT_BIT;
pushConstantRanges[0].offset = 0;
pushConstantRanges[0].size = sizeof(float)*3;
//pushConstantRanges[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
//pushConstantRanges[1].offset = sizeof(float);
//pushConstantRanges[1].size = 2*sizeof(float);
pipeline_layout_create_info.pushConstantRangeCount = 1;
pipeline_layout_create_info.pPushConstantRanges = &pushConstantRanges[0];
VK_CHECK(vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &m_pipelineLayout));
}
void FaceApp::setup_descriptor_pool()
{
std::vector<VkDescriptorPoolSize> pool_sizes = {
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = (kTextureMax *2)
},
{
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = ((kTextureMax + 1)*2)
},
// 如果需要其他类型的描述符,在这里添加
};
VkDescriptorPoolCreateInfo descriptor_pool_info{};
descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptor_pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size());
descriptor_pool_info.pPoolSizes = pool_sizes.data();
descriptor_pool_info.maxSets = kTextureMax + (kTextureMax + 1 + kTextureMax);
descriptor_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool));
}
void FaceApp::setup_descriptor_set()
{
m_descriptor_sets_left.resize(kTextureMax);
std::vector<VkDescriptorSetLayout> layouts(kTextureMax, m_descriptorSetLayout);
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = descriptor_pool;
alloc_info.pSetLayouts = layouts.data();
alloc_info.descriptorSetCount = m_descriptor_sets_left.size();
VK_CHECK(vkAllocateDescriptorSets(device, &alloc_info, m_descriptor_sets_left.data()));
update_descriptor_set(m_texs_left, m_descriptor_sets_left);
m_descriptor_sets_right.resize(kTextureMax);
VK_CHECK(vkAllocateDescriptorSets(device, &alloc_info, m_descriptor_sets_right.data()));
update_descriptor_set(m_texs_left, m_descriptor_sets_right);
}
void FaceApp::update_descriptor_set(vector<Texture>& texs, vector<VkDescriptorSet>& descriptSet)
{
for (int i = 0; i < kTextureMax; ++i)
{
if (texs[i].image == VK_NULL_HANDLE)
{
break;
}
VkDescriptorBufferInfo buffer_descriptor{};
buffer_descriptor.buffer = uniform_buffer_vs;
buffer_descriptor.range = VK_WHOLE_SIZE;
buffer_descriptor.offset = 0;
VkDescriptorImageInfo image_descriptor;
image_descriptor.imageView = texs[i].view;
image_descriptor.sampler = texs[i].sampler;
image_descriptor.imageLayout = texs[i].image_layout;
VkWriteDescriptorSet write_descriptor_set_uniform{};
write_descriptor_set_uniform.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor_set_uniform.dstSet = descriptSet[i];
write_descriptor_set_uniform.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
write_descriptor_set_uniform.dstBinding = 0;
write_descriptor_set_uniform.pBufferInfo = &buffer_descriptor;
write_descriptor_set_uniform.descriptorCount = 1;
VkWriteDescriptorSet write_descriptor_set_image{};
write_descriptor_set_image.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor_set_image.dstSet = descriptSet[i];
write_descriptor_set_image.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_descriptor_set_image.dstBinding = 1;
write_descriptor_set_image.pImageInfo = &image_descriptor;
write_descriptor_set_image.descriptorCount = 1;
if (kThick)
{
// 第二个纹理描述符 - 假设你的第二个纹理变量名为 tex_demo1
VkDescriptorImageInfo image_descriptor1;
image_descriptor1.imageView = m_texs_thick[i].view;
image_descriptor1.sampler = m_texs_thick[i].sampler;
image_descriptor1.imageLayout = m_texs_thick[i].image_layout;
// 添加第二个纹理的写入描述符
VkWriteDescriptorSet write_descriptor_set_image1{};
write_descriptor_set_image1.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor_set_image1.dstSet = descriptSet[i];
write_descriptor_set_image1.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_descriptor_set_image1.dstBinding = 2; // 绑定到位置2
write_descriptor_set_image1.pImageInfo = &image_descriptor1;
write_descriptor_set_image1.descriptorCount = 1;
std::vector<VkWriteDescriptorSet> write_descriptor_sets =
{
write_descriptor_set_uniform,
write_descriptor_set_image,
write_descriptor_set_image1, // 添加第二个纹理
};
vkUpdateDescriptorSets(device, static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
}
else
{
std::vector<VkWriteDescriptorSet> write_descriptor_sets =
{
write_descriptor_set_uniform,
write_descriptor_set_image,
};
vkUpdateDescriptorSets(device, static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
}
}
}
void FaceApp::render(VkCommandBuffer commandBuffer, long long frameTime)
{
std::unique_lock<std::mutex> lock(mtx);
std::unique_lock<std::mutex> lock_point(mtx_point);
//Application::render(commandBuffer);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout_bg, 0, 1, &m_descriptor_set_bg, 0, NULL);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline_bg);
vkCmdPushConstants(commandBuffer, m_pipelineLayout_bg, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float), &myFloatValue);
vkCmdDraw(commandBuffer, 6, 1, 0, 0);
if (cur_left)
{
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_sets_left[_curMotionIndex], 0, NULL);
}
else
{
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptor_sets_right[_curMotionIndex], 0, NULL);
}
float fsValues[3] = { myFloatValue, 0 , 0};
if (_curMotionIndex < _curMotions.size())
{
if (_curFrameIndex < _curMotions[_curMotionIndex].frames.size())
{
float ux = _curMotions[_curMotionIndex].frames[_curFrameIndex].x;
float uy = _curMotions[_curMotionIndex].frames[_curFrameIndex].y;
fsValues[1] = ux;
fsValues[2] = uy;
}
}
//fsValues[1] = 0;
//fsValues[2] = 360;
vkCmdPushConstants(commandBuffer, m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT| VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(fsValues), &fsValues);
//vkCmdPushConstants(commandBuffer, m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(fsValues), fsValues);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
VkDeviceSize offsets[1] = { 0 };
VkBuffer vertexBuffers[] = { m_vertexBuffer };
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer, 0, VK_INDEX_TYPE_UINT32);
#ifdef _WIN32
vkCmdDrawIndexed(commandBuffer, obj_indices.size(), 1, 0, 0, 0);
#else
if (getCurrentTimeMillis() - last_update_time < 2000)
{
vkCmdDrawIndexed(commandBuffer, obj_indices.size(), 1, 0, 0, 0);
}
#endif
}
void FaceApp::createVmaAllocator()
{
//VmaAllocatorCreateInfo allocatorInfo = {};
//allocatorInfo.physicalDevice = physicalDevice;
//allocatorInfo.device = device;
//allocatorInfo.instance = instance;
//allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0;
//vmaCreateAllocator(&allocatorInfo, &allocator);
// 1. 设置 Vulkan 函数指针
VmaVulkanFunctions vulkanFunctions{};
vulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
// 2. 配置 Allocator
VmaAllocatorCreateInfo allocatorInfo{};
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device;
allocatorInfo.instance = instance;
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0;
allocatorInfo.pVulkanFunctions = &vulkanFunctions;
VkResult result = vmaCreateAllocator(&allocatorInfo, &allocator);
}
void FaceApp::initVulkan()
{
Application::initVulkan();
createVmaAllocator();
LoadOBJ("face_picture_3dmax.obj", obj_vertices, obj_indices);
m_texs_left.resize(kTextureMax);
m_texs_right.resize(kTextureMax);
if (kThick)
{
m_texs_thick.resize(kTextureMax);
}
std::vector<unsigned char> data = readFileUnsignedChar("dummy.png", false);
unsigned error = lodepng::decode(dummy_data, dummy_w, dummy_h, data, LCT_RGBA, 8);
for (int i = 0; i < kTextureInit; ++i)
{
string id_str = std::to_string(i);
loadTexture(dummy_data, dummy_data.size(), dummy_w, dummy_h, m_texs_left[i], true, commandPool, "dummy.png_left_" + id_str);
loadTexture(dummy_data, dummy_data.size(), dummy_w, dummy_h, m_texs_right[i], true, commandPool, "dummy.png_right_" + id_str);
if (kThick)
{
loadTexture(dummy_data, dummy_data.size(), dummy_w, dummy_h, m_texs_thick[i], true, commandPool, "dummy.png_thick_" + id_str);
}
}
loadTexture("out.png", tex_bg, true, commandPool);
createVertexBuffer();
createUniformBuffer();
setup_descriptor_pool();
setup_descriptor_set_layout();
setup_descriptor_set();
create_face_pipelines();
setup_descriptor_set_layout_bg();
setup_descriptor_set_bg();
create_pipelines_bg();
uploadVertexData();
last_update_time = getCurrentTimeMillis();
//changeMotion(_initArg.motion);
_running = true;
faceAppInited = true;
#if _WIN32
std::vector<float> floatArray;
std::string& str = HardCodeData::Get().face_result_point_str;
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, ',')) {
floatArray.push_back(std::stof(token));
}
//ReceiveFacePoint(floatArray.data(), floatArray.size() / 3, 480, 480);
#endif
}
void FaceApp::update_uniform_buffers()
{
uint32_t width = 480;
uint32_t height = 480;
float zoom = 2;
// Vertex shader
ubo_vs.projection = glm::perspective(glm::radians(60.0f), static_cast<float>(width) / static_cast<float>(height), 0.001f, 256.0f);
glm::mat4 view_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, zoom));
ubo_vs.model = view_matrix * glm::translate(glm::mat4(1.0f), camera_pos);
ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
ubo_vs.model = glm::rotate(ubo_vs.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
ubo_vs.view_pos = glm::vec4(0.0f, 0.0f, -zoom, 0.0f);
memcpy(uniform_buffer_mapped, &ubo_vs, sizeof(ubo_vs));
}
void FaceApp::createVertexBuffer()
{
VkDeviceSize vertexBufferSize = sizeof(TextureLoadingVertexStructure) * obj_vertices.size();
VkDeviceSize indexBufferSize = sizeof(uint32_t) * obj_indices.size();
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = vertexBufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_vertexBuffer, &m_vertexBufferAllocation, nullptr);
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_stagingBuffer, &m_stagingBufferAllocation, nullptr);
bufferInfo.size = indexBufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &m_indexBuffer, &m_indexBufferAllocation, nullptr);
}
void FaceApp::uploadVertexData() {
void* data;
vmaMapMemory(allocator, m_stagingBufferAllocation, &data);
memcpy(data, obj_vertices.data(), sizeof(TextureLoadingVertexStructure) * obj_vertices.size());
vmaUnmapMemory(allocator, m_stagingBufferAllocation);
copyBuffer(m_stagingBuffer, m_vertexBuffer, sizeof(TextureLoadingVertexStructure) * obj_vertices.size());
vmaMapMemory(allocator, m_stagingBufferAllocation, &data);
memcpy(data, obj_indices.data(), sizeof(uint32_t) * obj_indices.size());
vmaUnmapMemory(allocator, m_stagingBufferAllocation);
copyBuffer(m_stagingBuffer, m_indexBuffer, sizeof(uint32_t) * obj_indices.size());
}
void FaceApp::update_face_vertex_buffer(float* pos, int pointCount)
{
if(!isInited())
{
return;
}
std::lock_guard<std::mutex> lock(mtx_point);
last_update_time = getCurrentTimeMillis();
for (int i = 0; i < obj_vertices.size(); ++i)
{
int face_index = obj_vertices_map[HardCodeData::Get().indexMap[i]];
float x = pos[face_index * 3 + 0];
float y = pos[face_index * 3 + 1];
float z = pos[face_index * 3 + 2];
obj_vertices[i].pos[0] = x;
obj_vertices[i].pos[1] = y;
obj_vertices[i].pos[2] = z;
}
calculateVertexNormals(obj_vertices, obj_indices);
uploadVertexData();
}
void FaceApp::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
VkBufferCopy copyRegion = {};
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
endSingleTimeCommands(commandBuffer);
}
VkCommandBuffer FaceApp::beginSingleTimeCommands() {
VkCommandBufferAllocateInfo allocInfo = { 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 = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
return commandBuffer;
}
void FaceApp::endSingleTimeCommands(VkCommandBuffer commandBuffer) {
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo = { 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 FaceApp::createUniformBuffer()
{
VkDeviceSize bufferSize = sizeof(ubo_vs);
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = bufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
// 创建缓冲区和内存分配
vmaCreateBuffer(allocator, &bufferInfo, &allocInfo,
&uniform_buffer_vs,
&uniform_buffer_allocation,
nullptr);
// 映射内存以便直接写入
vmaMapMemory(allocator, uniform_buffer_allocation, &uniform_buffer_mapped);
update_uniform_buffers();
}
void FaceApp::create_pipelines_bg()
{
VkPipelineInputAssemblyStateCreateInfo input_assembly_state{};
input_assembly_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly_state.flags = 0;
input_assembly_state.primitiveRestartEnable = VK_FALSE;
VkPipelineRasterizationStateCreateInfo rasterization_state{};
rasterization_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
rasterization_state.cullMode = VK_CULL_MODE_NONE;
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterization_state.flags = 0;
rasterization_state.depthClampEnable = VK_FALSE;
rasterization_state.lineWidth = 1.0f;
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.colorWriteMask = 0xf;
VkPipelineColorBlendStateCreateInfo colorBlending{};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {};
depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil_state.depthTestEnable = VK_FALSE;
depth_stencil_state.depthWriteEnable = VK_FALSE;
depth_stencil_state.depthCompareOp = VK_COMPARE_OP_GREATER;
depth_stencil_state.front = depth_stencil_state.back;
depth_stencil_state.back.compareOp = VK_COMPARE_OP_ALWAYS;
VkPipelineViewportStateCreateInfo viewport_state{};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.scissorCount = 1;
viewport_state.flags = 0;
VkPipelineMultisampleStateCreateInfo multisample_state{};
multisample_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisample_state.flags = 0;
// 视口状态
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swapChainExtent.width;
viewport.height = (float)swapChainExtent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
VkRect2D scissor{};
scissor.offset = { 0, 0 };
scissor.extent = swapChainExtent;
VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
auto vertShaderCode = readFile("shaders/bg.vert.spv");
auto fragShaderCode = readFile("shaders/bg.frag.spv");
VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(this->device, 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 shader_stages[] = { vertShaderStageInfo, fragShaderStageInfo };
VkPipelineVertexInputStateCreateInfo vertex_input_state{};
vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
VkGraphicsPipelineCreateInfo pipeline_create_info{};
pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_create_info.layout = m_pipelineLayout_bg;
pipeline_create_info.renderPass = renderPass;
pipeline_create_info.flags = 0;
pipeline_create_info.basePipelineIndex = -1;
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_create_info.pVertexInputState = &vertex_input_state;
pipeline_create_info.pInputAssemblyState = &input_assembly_state;
pipeline_create_info.pRasterizationState = &rasterization_state;
pipeline_create_info.pColorBlendState = &colorBlending; //&color_blend_state;
pipeline_create_info.pMultisampleState = &multisample_state;
pipeline_create_info.pViewportState = &viewport_state;
pipeline_create_info.pDepthStencilState = &depth_stencil_state;
//pipeline_create_info.pDynamicState = &dynamic_state;
pipeline_create_info.pViewportState = &viewportState;
pipeline_create_info.stageCount = 2;
pipeline_create_info.pStages = shader_stages;
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr, &m_graphicsPipeline_bg));
// 销毁着色器模块
vkDestroyShaderModule(device, fragShaderModule, nullptr);
vkDestroyShaderModule(device, vertShaderModule, nullptr);
}
void FaceApp::setup_descriptor_set_layout_bg()
{
VkDescriptorSetLayoutBinding set_layout_binding{};
set_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
set_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
set_layout_binding.binding = 0;
set_layout_binding.descriptorCount = 1;
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings ={set_layout_binding };
VkDescriptorSetLayoutCreateInfo descriptor_layout{};
descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
descriptor_layout.pBindings = set_layout_bindings.data();
descriptor_layout.bindingCount = static_cast<uint32_t>(set_layout_bindings.size());
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptor_layout, nullptr, &m_descriptorSetLayout_bg));
VkPipelineLayoutCreateInfo pipeline_layout_create_info{};
pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_create_info.setLayoutCount = 1;
pipeline_layout_create_info.pSetLayouts = &m_descriptorSetLayout_bg;
VkPushConstantRange pushConstantRanges[1];
pushConstantRanges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
pushConstantRanges[0].offset = 0;
pushConstantRanges[0].size = sizeof(float);
pipeline_layout_create_info.pushConstantRangeCount = 1;
pipeline_layout_create_info.pPushConstantRanges = &pushConstantRanges[0];
VK_CHECK(vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &m_pipelineLayout_bg));
}
void FaceApp::setup_descriptor_set_bg()
{
VkDescriptorSetAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = descriptor_pool;
alloc_info.pSetLayouts = &m_descriptorSetLayout_bg;
alloc_info.descriptorSetCount = 1;
VK_CHECK(vkAllocateDescriptorSets(device, &alloc_info, &m_descriptor_set_bg));
VkDescriptorImageInfo image_descriptor;
image_descriptor.imageView = tex_bg.view;
image_descriptor.sampler = tex_bg.sampler;
image_descriptor.imageLayout = tex_bg.image_layout;
VkWriteDescriptorSet write_descriptor_set{};
write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor_set.dstSet = m_descriptor_set_bg;
write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
write_descriptor_set.dstBinding = 0;
write_descriptor_set.pImageInfo = &image_descriptor;
write_descriptor_set.descriptorCount = 1;
std::vector<VkWriteDescriptorSet> write_descriptor_sets = { write_descriptor_set };
vkUpdateDescriptorSets(device, static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
}
void FaceApp::destroyTexture(VkDevice device, Texture& texture) {
// 注意销毁顺序:先销毁依赖对象,后销毁被依赖对象
// 1. 销毁采样器
if (texture.sampler != VK_NULL_HANDLE) {
vkDestroySampler(device, texture.sampler, nullptr);
texture.sampler = VK_NULL_HANDLE;
}
// 2. 销毁图像视图
if (texture.view != VK_NULL_HANDLE) {
vkDestroyImageView(device, texture.view, nullptr);
texture.view = VK_NULL_HANDLE;
}
// 3. 销毁图像
if (texture.image != VK_NULL_HANDLE) {
vkDestroyImage(device, texture.image, nullptr);
texture.image = VK_NULL_HANDLE;
}
// 4. 释放设备内存
if (texture.device_memory != VK_NULL_HANDLE) {
vkFreeMemory(device, texture.device_memory, nullptr);
texture.device_memory = VK_NULL_HANDLE;
//std::cout << "vkFreeMemory device_memory " << texture.texture_path << std::endl;
}
if (texture.stagingBuffer != VK_NULL_HANDLE)
{
vkDestroyBuffer(device, texture.stagingBuffer, nullptr);
texture.stagingBuffer = VK_NULL_HANDLE;
}
if (texture.stagingBufferMemory != VK_NULL_HANDLE)
{
vkFreeMemory(device, texture.stagingBufferMemory, nullptr);
//std::cout << "vkFreeMemory stagingBufferMemory " << texture.texture_path << std::endl;
texture.stagingBufferMemory = VK_NULL_HANDLE;
}
}
void FaceApp::cleanupResources(VkDevice device, VmaAllocator allocator) {
// 销毁图形管线
if (m_graphicsPipeline != VK_NULL_HANDLE) {
vkDestroyPipeline(device, m_graphicsPipeline, nullptr);
m_graphicsPipeline = VK_NULL_HANDLE;
}
// 销毁管线布局
if (m_pipelineLayout != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
m_pipelineLayout = VK_NULL_HANDLE;
}
// 销毁描述符集布局
if (m_descriptorSetLayout != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(device, m_descriptorSetLayout, nullptr);
m_descriptorSetLayout = VK_NULL_HANDLE;
}
// 销毁图形管线
if (m_graphicsPipeline_bg != VK_NULL_HANDLE) {
vkDestroyPipeline(device, m_graphicsPipeline_bg, nullptr);
m_graphicsPipeline_bg = VK_NULL_HANDLE;
}
// 销毁管线布局
if (m_pipelineLayout_bg != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(device, m_pipelineLayout_bg, nullptr);
m_pipelineLayout_bg = VK_NULL_HANDLE;
}
// 销毁描述符集布局
if (m_descriptorSetLayout_bg != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(device, m_descriptorSetLayout_bg, nullptr);
m_descriptorSetLayout_bg = VK_NULL_HANDLE;
}
// 销毁顶点缓冲区
if (m_vertexBuffer != VK_NULL_HANDLE) {
vkDestroyBuffer(device, m_vertexBuffer, nullptr);
m_vertexBuffer = VK_NULL_HANDLE;
}
if (m_vertexBufferAllocation != VK_NULL_HANDLE) {
vmaFreeMemory(allocator, m_vertexBufferAllocation);
m_vertexBufferAllocation = VK_NULL_HANDLE;
}
// 销毁暂存缓冲区
if (m_stagingBuffer != VK_NULL_HANDLE) {
vkDestroyBuffer(device, m_stagingBuffer, nullptr);
m_stagingBuffer = VK_NULL_HANDLE;
}
if (m_stagingBufferAllocation != VK_NULL_HANDLE) {
vmaFreeMemory(allocator, m_stagingBufferAllocation);
m_stagingBufferAllocation = VK_NULL_HANDLE;
}
// 销毁索引缓冲区
if (m_indexBuffer != VK_NULL_HANDLE) {
vkDestroyBuffer(device, m_indexBuffer, nullptr);
m_indexBuffer = VK_NULL_HANDLE;
}
if (m_indexBufferAllocation != VK_NULL_HANDLE) {
vmaFreeMemory(allocator, m_indexBufferAllocation);
m_indexBufferAllocation = VK_NULL_HANDLE;
}
if (descriptor_pool != VK_NULL_HANDLE)
{
vkDestroyDescriptorPool(device, descriptor_pool, nullptr);
descriptor_pool = VK_NULL_HANDLE;
}
// 清空描述符集列表(不需要单独销毁,由描述符池管理)
m_descriptor_sets_left.clear();
m_descriptor_sets_right.clear();
}
void FaceApp::cleanup()
{
vkDeviceWaitIdle(device);
if (uniform_buffer_mapped != nullptr)
{
vmaUnmapMemory(allocator, uniform_buffer_allocation);
uniform_buffer_mapped = nullptr;
}
if (uniform_buffer_vs != VK_NULL_HANDLE)
{
vmaDestroyBuffer(allocator, uniform_buffer_vs, uniform_buffer_allocation);
uniform_buffer_vs = VK_NULL_HANDLE;
uniform_buffer_allocation = VK_NULL_HANDLE; // 可选,但推荐重置
}
cleanupResources(device, allocator);
for (int i = 0; i < this->m_texs_left.size(); ++i)
{
destroyTexture(device, m_texs_left[i]);
}
for (int i = 0; i < this->m_texs_right.size(); ++i)
{
destroyTexture(device, m_texs_right[i]);
}
destroyTexture(device, tex_bg);
vkDestroyCommandPool(device, commandPool, nullptr);
vkDestroyCommandPool(device, commandPool_ex, nullptr);
Application::cleanup();
//if (allocator != VK_NULL_HANDLE) {
// vmaDestroyAllocator(allocator);
// allocator = VK_NULL_HANDLE;
//}
}
void FaceApp::SetInitArg(const char* arg)
{
_initArg = json::parse(arg);
}
void FaceApp::drawFrame(long long frameTime)
{
if (!_running)
{
return;
}
// if (_motionState == loading_next_motion)
// {
// int i = _nextMotionIndex;
// //for (int i = 0; i < _curMotion.png_names.size(); ++i)
// {
//
//#ifdef _WIN32
// string path = "pic";
// string path_name = path + "/" + _nextMotion.name + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
// loadTextureExample(UTF8ToWideString(path_name), m_texs_next[i], true);
//#else
// //string path = _curMotion.type + "/" + _curMotion.technique + "/" + _curMotion.step + "/" + _curMotion.show_type;
// string path = "pic";
// string path_name = path + "/" + _nextMotion.type + "/" + _nextMotion.png_names[i];// +std::to_string(i) + ".png";
// loadTexture(path_name, m_texs_next[i], true);
//#endif // _WIN32
//
// _nextMotionIndex++;
// if (_nextMotionIndex >= _nextMotion.png_names.size())
// {
// _motionState = load_next_motion_finished;
// _callback_loadfinish(_nextMotion.name);
// }
// }
// }
std::unique_lock lock(changeMotionMtx);
if (_curMotions.size() > 0)
{
static long long game_time = 0;
game_time += frameTime;
long long actionTime = (1000 / _initArg.action_fps);
if (game_time > actionTime)
{
if (_curFrameIndex < _curMotions[_curMotionIndex].frames.size() - 1)
{
_curFrameIndex += 1;
}
else
{
if (_curMotionIndex < _curMotions.size() - 1)
{
_curMotionIndex++;
_curFrameIndex = 0;
}
else
{
if (_animationFinishedCallback != nullptr)
{
_animationFinishedCallback();
}
if (_animationLoop)
{
_curMotionIndex = 0;
_curFrameIndex = 0;
}
else
{
_animationFinishedCallback = nullptr;
}
}
}
game_time = game_time - actionTime;
}
}
Application::drawFrame(frameTime);
}
//void FaceApp::changeMotion(const char* motion_type)
//{
// //Motion motion = json::parse(json);
// changeMotion(motion);
//}
string FaceApp::preLoadMotionList(string motion_list_str, Callback callback)
{
if (_isLoadMotion)
{
return "failue load not finished";
}
_isLoadMotion = true;
_callback_loadfinish = callback;
_preLoadMotions.clear();
json j = json::parse(motion_list_str);
MotionList motion_list = j.get<MotionList>();
_preLoadMotions = motion_list.motions;
worker_ = std::thread(&FaceApp::loadMotionThread, this);
return "ok";
}
void FaceApp::loadMotionThread()
{
while (!_running)
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
vector<Texture>* load_text = nullptr;
if (cur_left)
{
load_text = &m_texs_right;
}
else
{
load_text = &m_texs_left;
}
vector<Texture>& pre_texs = *load_text;
for (int i = 0; i < _preLoadMotions.size(); ++i)
{
if (pre_texs[i].image == VK_NULL_HANDLE)
{
loadTexture(dummy_data, dummy_data.size(), dummy_w, dummy_h, pre_texs[i], true, commandPool, "");
}
#ifdef _WIN32
string path = "pic";
string path_name = path + "/" + _preLoadMotions[i].name + "/" + _preLoadMotions[i].name + "ex.png";
loadTextureExample(UTF8ToWideString(path_name), pre_texs[i], true, commandPool_ex);
#else
string path = "pic";
string path_name = path + "/" + _preLoadMotions[i].name + "/" + _preLoadMotions[i].name + "ex.png";
loadTexture(path_name, pre_texs[i], true, commandPool_ex);
#endif // _WIN32
}
_isLoadMotion = false;
_callback_loadfinish();
}
void FaceApp::changeMotionList(AnimationFinishedCallback callback, bool loop)
{
if (_isLoadMotion)
{
return;
}
std::unique_lock<std::mutex> lock_changeMotion(changeMotionMtx);
//for (int i = 0; i < _preLoadMotions.size(); ++i)
//{
// destroyTexture(device, m_texs[i]);
//}
//for (int i = 0; i < _preLoadMotions.size(); ++i)
//{
// m_texs[i] = m_texs_next[i];
// //m_texs_next[i].reset();
//}
if (cur_left)
{
update_descriptor_set(m_texs_right, m_descriptor_sets_right);
cur_left = false;
}
else
{
update_descriptor_set(m_texs_left, m_descriptor_sets_left);
cur_left = true;
}
_curMotions = _preLoadMotions;
_curFrameIndex = 0;
_curMotionIndex = 0;
_animationFinishedCallback = callback;
_animationLoop = loop;
}