通议灵码修改过的。

This commit is contained in:
xsl
2025-09-14 21:52:08 +08:00
parent ef5f391ef5
commit 8e1c574122
2 changed files with 409 additions and 193 deletions
+256 -49
View File
@@ -1,6 +1,4 @@
#include "texture_loading.h"
#include "texture_loading.h"
TextureLoading* TextureLoading::loadTextIns = nullptr; TextureLoading* TextureLoading::loadTextIns = nullptr;
TextureLoading::TextureLoading() TextureLoading::TextureLoading()
@@ -19,9 +17,18 @@ TextureLoading::~TextureLoading()
// Note : Inherited destructor cleans up resources stored in base class // Note : Inherited destructor cleans up resources stored in base class
vkDestroyPipeline(get_device().get_handle(), pipelines.solid, nullptr); vkDestroyPipeline(get_device().get_handle(), pipelines.solid, nullptr);
if (pipelines.background != VK_NULL_HANDLE) {
vkDestroyPipeline(get_device().get_handle(), pipelines.background, nullptr);
}
vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr); vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr);
if (pipeline_layout_bg != VK_NULL_HANDLE) {
vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout_bg, nullptr);
}
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr); vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr);
if (descriptor_set_layout_bg != VK_NULL_HANDLE) {
vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout_bg, nullptr);
}
} }
destroy_texture(texture); destroy_texture(texture);
@@ -43,19 +50,23 @@ void TextureLoading::request_gpu_features(vkb::PhysicalDevice &gpu)
void TextureLoading::destroy_texture(Texture texture) void TextureLoading::destroy_texture(Texture texture)
{ {
vkDestroyImageView(get_device().get_handle(), texture.view, nullptr); if (texture.view != VK_NULL_HANDLE) vkDestroyImageView(get_device().get_handle(), texture.view, nullptr);
vkDestroyImage(get_device().get_handle(), texture.image, nullptr); if (texture.image != VK_NULL_HANDLE) vkDestroyImage(get_device().get_handle(), texture.image, nullptr);
vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr); if (texture.sampler != VK_NULL_HANDLE) vkDestroySampler(get_device().get_handle(), texture.sampler, nullptr);
vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr); if (texture.device_memory != VK_NULL_HANDLE) vkFreeMemory(get_device().get_handle(), texture.device_memory, nullptr);
// Reset struct
texture = { 0 };
} }
void TextureLoading::build_command_buffers() void TextureLoading::build_command_buffers()
{ {
VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info(); VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();
// 注意:深度缓冲区清除值改为 1.0f (最远)
VkClearValue clear_values[2]; VkClearValue clear_values[2];
clear_values[0].color = default_clear_color; clear_values[0].color = default_clear_color;
clear_values[1].depthStencil = {0.0f, 0}; clear_values[1].depthStencil = { 1.0f, 0 }; // 使用 1.0f 作为深度清除值
VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info(); VkRenderPassBeginInfo render_pass_begin_info = vkb::initializers::render_pass_begin_info();
render_pass_begin_info.renderPass = render_pass; render_pass_begin_info.renderPass = render_pass;
@@ -63,7 +74,7 @@ void TextureLoading::build_command_buffers()
render_pass_begin_info.renderArea.offset.y = 0; render_pass_begin_info.renderArea.offset.y = 0;
render_pass_begin_info.renderArea.extent.width = width; render_pass_begin_info.renderArea.extent.width = width;
render_pass_begin_info.renderArea.extent.height = height; render_pass_begin_info.renderArea.extent.height = height;
render_pass_begin_info.clearValueCount = 2; render_pass_begin_info.clearValueCount = 2; // 现在清除颜色和深度
render_pass_begin_info.pClearValues = clear_values; render_pass_begin_info.pClearValues = clear_values;
for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i) for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i)
@@ -81,6 +92,19 @@ void TextureLoading::build_command_buffers()
VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0); VkRect2D scissor = vkb::initializers::rect2D(width, height, 0, 0);
vkCmdSetScissor(draw_cmd_buffers[i], 0, 1, &scissor); vkCmdSetScissor(draw_cmd_buffers[i], 0, 1, &scissor);
// --- 绘制全屏背景 ---
if (cam_text.image != VK_NULL_HANDLE && cam_text.view != VK_NULL_HANDLE && cam_text.sampler != VK_NULL_HANDLE) {
vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.background);
vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_bg, 0, 1, &descriptor_set_bg, 0, NULL);
// 绘制一个三角形 strip,覆盖整个屏幕 (NDC -1 to 1)
// 顶点顺序: (-1,-1), (1,-1), (-1,1), (1,1)
vkCmdDraw(draw_cmd_buffers[i], 4, 1, 0, 0); // 4 个顶点, 1 个实例, 从索引 0 开始
}
// --- 绘制前景四边形 ---
// 确保前景管线和描述符集有效
if (pipelines.solid != VK_NULL_HANDLE && descriptor_set != VK_NULL_HANDLE &&
vertex_buffer && index_buffer) {
vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, NULL); vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, NULL);
vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid); vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.solid);
@@ -89,8 +113,9 @@ void TextureLoading::build_command_buffers()
vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(draw_cmd_buffers[i], index_buffer->get_handle(), 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0); vkCmdDrawIndexed(draw_cmd_buffers[i], index_count, 1, 0, 0, 0);
}
draw_ui(draw_cmd_buffers[i]); draw_ui(draw_cmd_buffers[i]); // UI 通常在最后绘制
vkCmdEndRenderPass(draw_cmd_buffers[i]); vkCmdEndRenderPass(draw_cmd_buffers[i]);
@@ -98,9 +123,10 @@ void TextureLoading::build_command_buffers()
} }
} }
// 生成简单的测试图像数据(红绿蓝三色条)
// 生成简单的测试图像数据(红绿蓝三色条)
std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowStride = nullptr) { std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowStride = nullptr) {
int rowStride = width * 4; // RGBA 每个像素4字节 int rowStride = width * 4; // RGBA 每个像素4字节
if (outRowStride) { if (outRowStride) {
*outRowStride = rowStride; *outRowStride = rowStride;
} }
@@ -112,27 +138,27 @@ std::vector<uint8_t> generateSimpleTestImage(int width, int height, int* outRowS
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
int pixelOffset = y * rowStride + x * 4; int pixelOffset = y * rowStride + x * 4;
// 简单分成三个区域:红、绿、蓝 // 简单分成三个区域:红、绿、蓝
if (x < width / 3) { if (x < width / 3) {
// 红色区域 // 红色区域
imageData[pixelOffset] = 255; // R imageData[pixelOffset] = 255; // R
imageData[pixelOffset + 1] = 0; // G imageData[pixelOffset + 1] = 0; // G
imageData[pixelOffset + 2] = 0; // B imageData[pixelOffset + 2] = 0; // B
} }
else if (x < 2 * width / 3) { else if (x < 2 * width / 3) {
// 绿色区域 // 绿色区域
imageData[pixelOffset] = 0; // R imageData[pixelOffset] = 0; // R
imageData[pixelOffset + 1] = 255; // G imageData[pixelOffset + 1] = 255; // G
imageData[pixelOffset + 2] = 0; // B imageData[pixelOffset + 2] = 0; // B
} }
else { else {
// 蓝色区域 // 蓝色区域
imageData[pixelOffset] = 0; // R imageData[pixelOffset] = 0; // R
imageData[pixelOffset + 1] = 0; // G imageData[pixelOffset + 1] = 0; // G
imageData[pixelOffset + 2] = 255; // B imageData[pixelOffset + 2] = 255; // B
} }
imageData[pixelOffset + 3] = 255; // A (完全不透明) imageData[pixelOffset + 3] = 255; // A (完全不透明)
} }
} }
@@ -189,23 +215,26 @@ void TextureLoading::generate_quad()
void TextureLoading::setup_descriptor_pool() void TextureLoading::setup_descriptor_pool()
{ {
// Example uses one ubo and one image sampler // Example uses one ubo and two image samplers (one for foreground, one for background)
// 增加 Combined Image Sampler 的数量到 2
std::vector<VkDescriptorPoolSize> pool_sizes = std::vector<VkDescriptorPoolSize> pool_sizes =
{ {
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)}; vkb::initializers::descriptor_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2) // 改为 2
};
VkDescriptorPoolCreateInfo descriptor_pool_create_info = VkDescriptorPoolCreateInfo descriptor_pool_create_info =
vkb::initializers::descriptor_pool_create_info( vkb::initializers::descriptor_pool_create_info(
static_cast<uint32_t>(pool_sizes.size()), static_cast<uint32_t>(pool_sizes.size()),
pool_sizes.data(), pool_sizes.data(),
2); 2); // 最大描述符集数量改为 2
VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool)); VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool));
} }
void TextureLoading::setup_descriptor_set_layout() void TextureLoading::setup_descriptor_set_layout()
{ {
// Foreground descriptor set layout (UBO + Texture)
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings = std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings =
{ {
// Binding 0 : Vertex shader uniform buffer // Binding 0 : Vertex shader uniform buffer
@@ -213,7 +242,7 @@ void TextureLoading::setup_descriptor_set_layout()
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_VERTEX_BIT,
0), 0),
// Binding 1 : Fragment shader image sampler // Binding 1 : Fragment shader image sampler (foreground texture)
vkb::initializers::descriptor_set_layout_binding( vkb::initializers::descriptor_set_layout_binding(
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT,
@@ -226,6 +255,7 @@ void TextureLoading::setup_descriptor_set_layout()
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout)); VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout, nullptr, &descriptor_set_layout));
// Foreground pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_create_info = VkPipelineLayoutCreateInfo pipeline_layout_create_info =
vkb::initializers::pipeline_layout_create_info( vkb::initializers::pipeline_layout_create_info(
&descriptor_set_layout, &descriptor_set_layout,
@@ -234,8 +264,38 @@ void TextureLoading::setup_descriptor_set_layout()
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout)); VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout));
} }
// 新增:设置背景描述符集布局 (仅包含纹理)
void TextureLoading::setup_descriptor_set_layout_bg()
{
std::vector<VkDescriptorSetLayoutBinding> set_layout_bindings_bg =
{
// Binding 0 : Fragment shader image sampler (background texture)
vkb::initializers::descriptor_set_layout_binding(
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
VK_SHADER_STAGE_FRAGMENT_BIT,
0) // Binding 0 for background
};
VkDescriptorSetLayoutCreateInfo descriptor_layout_bg =
vkb::initializers::descriptor_set_layout_create_info(
set_layout_bindings_bg.data(),
static_cast<uint32_t>(set_layout_bindings_bg.size()));
VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &descriptor_layout_bg, nullptr, &descriptor_set_layout_bg));
// Background pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_create_info_bg =
vkb::initializers::pipeline_layout_create_info(
&descriptor_set_layout_bg,
1);
VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info_bg, nullptr, &pipeline_layout_bg));
}
void TextureLoading::setup_descriptor_set() void TextureLoading::setup_descriptor_set()
{ {
// Foreground descriptor set
VkDescriptorSetAllocateInfo alloc_info = VkDescriptorSetAllocateInfo alloc_info =
vkb::initializers::descriptor_set_allocate_info( vkb::initializers::descriptor_set_allocate_info(
descriptor_pool, descriptor_pool,
@@ -246,11 +306,11 @@ void TextureLoading::setup_descriptor_set()
VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*uniform_buffer_vs); VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*uniform_buffer_vs);
// Setup a descriptor image info for the current texture to be used as a combined image sampler // Setup a descriptor image info for the current foreground texture
VkDescriptorImageInfo image_descriptor; VkDescriptorImageInfo image_descriptor;
image_descriptor.imageView = texture.view; // The image's view (images are never directly accessed by the shader, but rather through views defining subresources) image_descriptor.imageView = texture.view;
image_descriptor.sampler = texture.sampler; // The sampler (Telling the pipeline how to sample the texture, including repeat, border, etc.) image_descriptor.sampler = texture.sampler;
image_descriptor.imageLayout = texture.image_layout; // The current layout of the image (Note: Should always fit the actual use, e.g. shader read) image_descriptor.imageLayout = texture.image_layout;
std::vector<VkWriteDescriptorSet> write_descriptor_sets = std::vector<VkWriteDescriptorSet> write_descriptor_sets =
{ {
@@ -260,20 +320,53 @@ void TextureLoading::setup_descriptor_set()
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0, 0,
&buffer_descriptor), &buffer_descriptor),
// Binding 1 : Fragment shader texture sampler // Binding 1 : Fragment shader texture sampler (foreground)
// Fragment shader: layout (binding = 1) uniform sampler2D samplerColor;
vkb::initializers::write_descriptor_set( vkb::initializers::write_descriptor_set(
descriptor_set, descriptor_set,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // The descriptor set will use a combined image sampler (sampler and image could be split) VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1, // Shader binding point 1 1,
&image_descriptor) // Pointer to the descriptor image for our texture &image_descriptor)
}; };
vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL); vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, NULL);
} }
// 新增:设置背景描述符集
void TextureLoading::setup_descriptor_set_bg()
{
// Background descriptor set
VkDescriptorSetAllocateInfo alloc_info_bg =
vkb::initializers::descriptor_set_allocate_info(
descriptor_pool,
&descriptor_set_layout_bg,
1);
VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &alloc_info_bg, &descriptor_set_bg));
// Setup a descriptor image info for the background texture (cam_text)
VkDescriptorImageInfo image_descriptor_bg;
// 注意:这里使用 cam_text
image_descriptor_bg.imageView = cam_text.view;
image_descriptor_bg.sampler = cam_text.sampler;
image_descriptor_bg.imageLayout = cam_text.image_layout; // 应该是 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
std::vector<VkWriteDescriptorSet> write_descriptor_sets_bg =
{
// Binding 0 : Fragment shader texture sampler (background)
vkb::initializers::write_descriptor_set(
descriptor_set_bg,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, // Binding 0 for background
&image_descriptor_bg)
};
vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets_bg.size()), write_descriptor_sets_bg.data(), 0, NULL);
}
void TextureLoading::prepare_pipelines() void TextureLoading::prepare_pipelines()
{ {
// --- 前景管线 ---
VkPipelineInputAssemblyStateCreateInfo input_assembly_state = VkPipelineInputAssemblyStateCreateInfo input_assembly_state =
vkb::initializers::pipeline_input_assembly_state_create_info( vkb::initializers::pipeline_input_assembly_state_create_info(
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
@@ -283,7 +376,7 @@ void TextureLoading::prepare_pipelines()
VkPipelineRasterizationStateCreateInfo rasterization_state = VkPipelineRasterizationStateCreateInfo rasterization_state =
vkb::initializers::pipeline_rasterization_state_create_info( vkb::initializers::pipeline_rasterization_state_create_info(
VK_POLYGON_MODE_FILL, VK_POLYGON_MODE_FILL,
VK_CULL_MODE_NONE, VK_CULL_MODE_NONE, // 保持不变,或根据需要调整
VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FRONT_FACE_COUNTER_CLOCKWISE,
0); 0);
@@ -298,11 +391,12 @@ void TextureLoading::prepare_pipelines()
&blend_attachment_state); &blend_attachment_state);
// Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept // Note: Using reversed depth-buffer for increased precision, so Greater depth values are kept
// 前景管线启用深度测试和写入
VkPipelineDepthStencilStateCreateInfo depth_stencil_state = VkPipelineDepthStencilStateCreateInfo depth_stencil_state =
vkb::initializers::pipeline_depth_stencil_state_create_info( vkb::initializers::pipeline_depth_stencil_state_create_info(
VK_TRUE, VK_TRUE, // depthTestEnable
VK_TRUE, VK_TRUE, // depthWriteEnable
VK_COMPARE_OP_GREATER); VK_COMPARE_OP_GREATER); // Reversed depth buffer
VkPipelineViewportStateCreateInfo viewport_state = VkPipelineViewportStateCreateInfo viewport_state =
vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0); vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0);
@@ -322,13 +416,13 @@ void TextureLoading::prepare_pipelines()
static_cast<uint32_t>(dynamic_state_enables.size()), static_cast<uint32_t>(dynamic_state_enables.size()),
0); 0);
// Load shaders // Load shaders (确保你有对应的 SPIR-V 文件)
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages; std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages;
// 假设着色器文件名为 texture.vert.spv 和 texture.frag.spv
shader_stages[0] = load_shader("texture_loading", "texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shader_stages[0] = load_shader("texture_loading", "texture.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shader_stages[1] = load_shader("texture_loading", "texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); shader_stages[1] = load_shader("texture_loading", "texture.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// Vertex bindings and attributes // Vertex bindings and attributes (用于前景 quad)
const std::vector<VkVertexInputBindingDescription> vertex_input_bindings = { const std::vector<VkVertexInputBindingDescription> vertex_input_bindings = {
vkb::initializers::vertex_input_binding_description(0, sizeof(TextureLoadingVertexStructure), VK_VERTEX_INPUT_RATE_VERTEX), vkb::initializers::vertex_input_binding_description(0, sizeof(TextureLoadingVertexStructure), VK_VERTEX_INPUT_RATE_VERTEX),
}; };
@@ -345,7 +439,7 @@ void TextureLoading::prepare_pipelines()
VkGraphicsPipelineCreateInfo pipeline_create_info = VkGraphicsPipelineCreateInfo pipeline_create_info =
vkb::initializers::pipeline_create_info( vkb::initializers::pipeline_create_info(
pipeline_layout, pipeline_layout, // 前景管线布局
render_pass, render_pass,
0); 0);
@@ -363,6 +457,93 @@ void TextureLoading::prepare_pipelines()
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &pipelines.solid)); VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info, nullptr, &pipelines.solid));
} }
// 新增:准备背景管线
void TextureLoading::prepare_pipeline_bg()
{
// --- 背景管线 (简单 quad, 全屏覆盖) ---
VkPipelineInputAssemblyStateCreateInfo input_assembly_state_bg =
vkb::initializers::pipeline_input_assembly_state_create_info(
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // 使用 Triangle Strip
0,
VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterization_state_bg =
vkb::initializers::pipeline_rasterization_state_create_info(
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_BACK_BIT, // 通常对全屏 quad 启用背面剔除,但这里可能不需要,因为是屏幕对齐的
VK_FRONT_FACE_COUNTER_CLOCKWISE,
0);
VkPipelineColorBlendAttachmentState blend_attachment_state_bg =
vkb::initializers::pipeline_color_blend_attachment_state(
0xf,
VK_FALSE); // 通常背景不需要混合
VkPipelineColorBlendStateCreateInfo color_blend_state_bg =
vkb::initializers::pipeline_color_blend_state_create_info(
1,
&blend_attachment_state_bg);
// 背景管线配置:启用深度测试,但禁用深度写入,使用 LESS 比较 (或 ALWAYS)
// 这样背景会被绘制,但不会影响前景物体的深度值(如果前景物体 Z 值更近)
VkPipelineDepthStencilStateCreateInfo depth_stencil_state_bg =
vkb::initializers::pipeline_depth_stencil_state_create_info(
VK_TRUE, // depthTestEnable - 启用深度测试
VK_FALSE, // depthWriteEnable - 禁用深度写入,让前景物体能正确遮挡背景
VK_COMPARE_OP_LESS); // 比较操作:如果片段的深度小于深度缓冲区中的值,则通过。
// 结合清除深度为 1.0 和前景使用 GREATER,这应该可以正确工作。
// 或者使用 VK_COMPARE_OP_ALWAYS 来强制绘制背景,忽略深度。
VkPipelineViewportStateCreateInfo viewport_state_bg =
vkb::initializers::pipeline_viewport_state_create_info(1, 1, 0);
VkPipelineMultisampleStateCreateInfo multisample_state_bg =
vkb::initializers::pipeline_multisample_state_create_info(
VK_SAMPLE_COUNT_1_BIT,
0);
// 背景管线不需要动态状态或顶点输入(如果顶点在着色器中生成)
std::vector<VkDynamicState> dynamic_state_enables_bg = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamic_state_bg =
vkb::initializers::pipeline_dynamic_state_create_info(
dynamic_state_enables_bg.data(),
static_cast<uint32_t>(dynamic_state_enables_bg.size()),
0);
// Load shaders for background (你需要创建对应的 SPIR-V 文件)
// 假设着色器文件名为 bg.vert.spv 和 bg.frag.spv
std::array<VkPipelineShaderStageCreateInfo, 2> shader_stages_bg;
shader_stages_bg[0] = load_shader("texture_loading", "bg.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shader_stages_bg[1] = load_shader("texture_loading", "bg.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
// 背景管线不需要顶点缓冲区输入
VkPipelineVertexInputStateCreateInfo vertex_input_state_bg = vkb::initializers::pipeline_vertex_input_state_create_info();
// vertex_input_state_bg 保持默认空状态即可
VkGraphicsPipelineCreateInfo pipeline_create_info_bg =
vkb::initializers::pipeline_create_info(
pipeline_layout_bg, // 背景管线布局
render_pass,
0);
pipeline_create_info_bg.pVertexInputState = &vertex_input_state_bg; // 空的顶点输入
pipeline_create_info_bg.pInputAssemblyState = &input_assembly_state_bg;
pipeline_create_info_bg.pRasterizationState = &rasterization_state_bg;
pipeline_create_info_bg.pColorBlendState = &color_blend_state_bg;
pipeline_create_info_bg.pMultisampleState = &multisample_state_bg;
pipeline_create_info_bg.pViewportState = &viewport_state_bg;
pipeline_create_info_bg.pDepthStencilState = &depth_stencil_state_bg;
pipeline_create_info_bg.pDynamicState = &dynamic_state_bg;
pipeline_create_info_bg.stageCount = static_cast<uint32_t>(shader_stages_bg.size());
pipeline_create_info_bg.pStages = shader_stages_bg.data();
VK_CHECK(vkCreateGraphicsPipelines(get_device().get_handle(), pipeline_cache, 1, &pipeline_create_info_bg, nullptr, &pipelines.background));
}
// Prepare and initialize uniform buffer containing shader uniforms // Prepare and initialize uniform buffer containing shader uniforms
void TextureLoading::prepare_uniform_buffers() void TextureLoading::prepare_uniform_buffers()
{ {
@@ -397,27 +578,35 @@ bool TextureLoading::prepare(const vkb::ApplicationOptions &options)
{ {
return false; return false;
} }
//load_texture();
// --- 初始化 cam_text 纹理对象 ---
// 注意:这里只是初始化结构体,图像内存等由外部函数分配
// cam_text = {0}; // 已在构造函数或销毁时重置
// --- 加载前景纹理 (示例) ---
int width = 640; int width = 640;
int height = 480; int height = 480;
int rowStride; int rowStride;
auto testImage = generateSimpleTestImage(width, height, &rowStride); auto testImage = generateSimpleTestImage(width, height, &rowStride);
size_t dataSize = testImage.size(); size_t dataSize = testImage.size();
std::cout << "Generated test image: " << width << "x" << height << std::endl; std::cout << "Generated test image: " << width << "x" << height << std::endl;
std::cout << "Row stride: " << rowStride << std::endl; std::cout << "Row stride: " << rowStride << std::endl;
std::cout << "Data size: " << dataSize << " bytes" << std::endl; std::cout << "Data size: " << dataSize << " bytes" << std::endl;
processWithVulkan(testImage.data(), width, height, 1, rowStride, dataSize, texture); processWithVulkan(testImage.data(), width, height, 1, rowStride, dataSize, texture);
// --- 生成前景几何体 ---
generate_quad(); generate_quad();
// --- 准备资源 ---
prepare_uniform_buffers(); prepare_uniform_buffers();
setup_descriptor_set_layout(); setup_descriptor_set_layout(); // 前景 DSL
prepare_pipelines(); setup_descriptor_set_layout_bg(); // 背景 DSL
setup_descriptor_pool(); prepare_pipelines(); // 前景管线
setup_descriptor_set(); prepare_pipeline_bg(); // 背景管线
setup_descriptor_pool(); // 描述符池 (已更新大小)
setup_descriptor_set(); // 前景 DS
setup_descriptor_set_bg(); // 背景 DS
build_command_buffers(); build_command_buffers();
prepared = true; prepared = true;
return true; return true;
@@ -430,7 +619,10 @@ void TextureLoading::render(float delta_time)
return; return;
} }
if (texture.width == 0) // 可以在这里添加逻辑来更新 cam_text 纹理
// 例如,如果 cam_text.image != VK_NULL_HANDLE,调用 updateTexture
if (texture.width == 0) // 检查前景纹理
{ {
return; return;
} }
@@ -459,10 +651,18 @@ std::unique_ptr<vkb::Application> create_texture_loading()
return std::make_unique<TextureLoading>(); return std::make_unique<TextureLoading>();
} }
// 外部函数保持不变
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize) void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize)
{ {
if (TextureLoading::Get()) {
TextureLoading::Texture& cam_texture = TextureLoading::Get()->cam_text; TextureLoading::Texture& cam_texture = TextureLoading::Get()->cam_text;
TextureLoading::Get()->processWithVulkan(data, width, height, format, rowStride, dataSize, cam_texture); TextureLoading::Get()->processWithVulkan(data, width, height, format, rowStride, dataSize, cam_texture);
// 可能需要重建命令缓冲区或更新描述符集,如果管线已经创建
// 这里简单地重建命令缓冲区
if (TextureLoading::Get()->prepared) {
TextureLoading::Get()->build_command_buffers();
}
}
} }
@@ -472,13 +672,20 @@ void TextureLoading::processWithVulkan(uint8_t* data, int width, int height, int
const VkPhysicalDevice& physicalDevice = get_device().get_gpu().get_handle(); const VkPhysicalDevice& physicalDevice = get_device().get_gpu().get_handle();
if (out_texture.image == VK_NULL_HANDLE) { if (out_texture.image == VK_NULL_HANDLE) {
createTexture(device, physicalDevice, width, height, format, out_texture); createTexture(device, physicalDevice, width, height, format, out_texture);
// 如果纹理是新创建的,并且管线已经准备好,需要更新描述符集
if (prepared && &out_texture == &cam_text) {
setup_descriptor_set_bg(); // 重新设置背景描述符集
}
} }
const VkCommandPool& commandPool = get_device().get_command_pool().get_handle(); const VkCommandPool& commandPool = get_device().get_command_pool().get_handle();
updateTexture(device, physicalDevice, commandPool, queue, data, width, height, updateTexture(device, physicalDevice, commandPool, queue, data, width, height,
rowStride, dataSize, out_texture); rowStride, dataSize, out_texture);
// 如果纹理被更新,并且管线已经准备好,可能需要重建命令缓冲区
// 这取决于你的应用逻辑。简单起见,在外部函数中处理。
} }
// --- 以下函数保持不变 ---
void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDevice, void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDevice,
int width, int height, int format, Texture& texture) { int width, int height, int format, Texture& texture) {
@@ -489,7 +696,7 @@ void TextureLoading::createTexture(VkDevice device, VkPhysicalDevice physicalDev
VkImageCreateInfo imageInfo = {}; VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D; imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; // 匹配 RGBA_8888 imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM; // Æ¥Åä RGBA_8888
imageInfo.extent.width = width; imageInfo.extent.width = width;
imageInfo.extent.height = height; imageInfo.extent.height = height;
imageInfo.extent.depth = 1; imageInfo.extent.depth = 1;
+23 -14
View File
@@ -1,10 +1,10 @@
#pragma once
#pragma once
#include <ktx.h> #include <ktx.h>
#include "api_vulkan_sample.h" #include "api_vulkan_sample.h"
// 顶点结构保持不变,因为背景 quad 可能不需要顶点缓冲区
struct TextureLoadingVertexStructure struct TextureLoadingVertexStructure
{ {
float pos[3]; float pos[3];
@@ -27,7 +27,7 @@ class TextureLoading : public ApiVulkanSample
}; };
Texture texture = { 0 }; Texture texture = { 0 };
Texture cam_text = {0}; Texture cam_text = { 0 }; // 将由外部函数初始化
std::unique_ptr<vkb::core::BufferC> vertex_buffer; std::unique_ptr<vkb::core::BufferC> vertex_buffer;
std::unique_ptr<vkb::core::BufferC> index_buffer; std::unique_ptr<vkb::core::BufferC> index_buffer;
@@ -45,26 +45,40 @@ class TextureLoading : public ApiVulkanSample
struct struct
{ {
VkPipeline solid; VkPipeline solid; // 原有前景管线
VkPipeline background; // 新增背景管线
} pipelines; } pipelines;
VkPipelineLayout pipeline_layout; // 管线布局
VkDescriptorSet descriptor_set; VkPipelineLayout pipeline_layout; // 前景管线布局
VkDescriptorSetLayout descriptor_set_layout; VkPipelineLayout pipeline_layout_bg; // 背景管线布局
// 描述符集
VkDescriptorSet descriptor_set; // 前景描述符集
VkDescriptorSet descriptor_set_bg; // 背景描述符集
// 描述符集布局
VkDescriptorSetLayout descriptor_set_layout; // 前景描述符集布局
VkDescriptorSetLayout descriptor_set_layout_bg; // 背景描述符集布局 (仅包含 combined image sampler)
static TextureLoading* Get() { static TextureLoading* Get() {
return loadTextIns; return loadTextIns;
} }
static TextureLoading* loadTextIns; static TextureLoading* loadTextIns;
TextureLoading(); TextureLoading();
~TextureLoading(); ~TextureLoading();
virtual void request_gpu_features(vkb::PhysicalDevice& gpu) override; virtual void request_gpu_features(vkb::PhysicalDevice& gpu) override;
void build_command_buffers() override; void build_command_buffers() override;
void draw(); void draw();
void generate_quad(); void generate_quad(); // 生成前景 quad
void setup_descriptor_pool(); void setup_descriptor_pool();
void setup_descriptor_set_layout(); void setup_descriptor_set_layout();
void setup_descriptor_set_layout_bg(); // 新增:设置背景描述符集布局
void setup_descriptor_set(); void setup_descriptor_set();
void setup_descriptor_set_bg(); // 新增:设置背景描述符集
void prepare_pipelines(); void prepare_pipelines();
void prepare_pipeline_bg(); // 新增:准备背景管线
void prepare_uniform_buffers(); void prepare_uniform_buffers();
void update_uniform_buffers(); void update_uniform_buffers();
bool prepare(const vkb::ApplicationOptions& options) override; bool prepare(const vkb::ApplicationOptions& options) override;
@@ -73,19 +87,14 @@ class TextureLoading : public ApiVulkanSample
virtual void on_update_ui_overlay(vkb::Drawer& drawer) override; virtual void on_update_ui_overlay(vkb::Drawer& drawer) override;
void destroy_texture(Texture texture); void destroy_texture(Texture texture);
public: // 现有函数保持不变
void processWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize, Texture& out_texture); void processWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize, Texture& out_texture);
void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, int format, Texture& texture); void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, int format, Texture& texture);
void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture); void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture);
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties); uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool); VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer); void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout); void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
}; };
std::unique_ptr<vkb::Application> create_texture_loading(); std::unique_ptr<vkb::Application> create_texture_loading();