Смесь веса SMAA текстура неяснаC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Смесь веса SMAA текстура неясна

Сообщение Anonymous »

Я пытаюсь использовать SMAA на Вулкане, но выходное изображение не является полным анти-алиатом.
Нравится это:
eRegexex. Blendtex не так ясно по сравнению с весовым изображением, которое происходит от smaademo
edgestex


изображение веса из smaademo

Так что я подозреваю, что проблема в проходе смешивания веса, но я пробовал все, что я могу, и это ничего не меняет. Iryoku/smaa
smaa_define.h
//
// SMAA common header file
//

// push constant, use for smaa render target metrics
layout(push_constant) uniform PushConstant
{
vec4 smaa_rt_metrics;
} pc;

#define SMAA_RT_METRICS pc.smaa_rt_metrics
#define SMAA_GLSL_4
#define SMAA_PRESET_ULTRA
< /code>
smaa_vert.h
//
// SMAA vertex shader common define
//

#include "SMAA_define.h"

#define SMAA_INCLUDE_PS 0
#include "SMAA.hlsl"

layout(location = 0) out vec2 texture_coord;
layout(location = 1) out vec2 pixel_coord;
layout(location = 2) out vec4 offset[3];

//
// fullscreen triangle
//
vec2 vertices[] =
{
{ -1, -1 },
{ 3, -1 },
{ -1, 3 },
};

vec2 texture_coords[] =
{
{ 0, 0 },
{ 2, 0 },
{ 0, 2 },
};

void set_gl_Position_and_texture_coord()
{
gl_Position = vec4(vertices[gl_VertexIndex], 0, 1);
texture_coord = texture_coords[gl_VertexIndex];
}
< /code>
smaa_frag.h
//
// SMAA fragment shader common define
//

#include "SMAA_define.h"

#define SMAA_INCLUDE_VS 0
#include "SMAA.hlsl"

layout(location = 0) in vec2 texture_coord;
layout(location = 1) in vec2 pixel_coord;
layout(location = 2) in vec4 offset[3];

layout(location = 0) out vec4 color;
< /code>
smaa_edge_detection.vert
#version 460

#include "SMAA_vert.h"

void main()
{
set_gl_Position_and_texture_coord();
SMAAEdgeDetectionVS(texture_coord, offset);
}
< /code>
smaa_edge_detection.frag
#version 460

#include "SMAA_frag.h"

layout(binding = 0) uniform sampler2D original_image;

void main()
{
color = vec4(SMAAColorEdgeDetectionPS(texture_coord, offset, original_image), 0.0, 0.0);
}
< /code>
smaa_blend_weight.vert
#version 460

#include "SMAA_vert.h"

void main()
{
set_gl_Position_and_texture_coord();
SMAABlendingWeightCalculationVS(texture_coord, pixel_coord, offset);
}
< /code>
smaa_blend_weight.frag
#version 460

#include "SMAA_frag.h"

layout(binding = 1) uniform sampler2D edges_texture;
layout(binding = 2) uniform sampler2D area_texture;
layout(binding = 3) uniform sampler2D search_texture;

void main()
{
color = SMAABlendingWeightCalculationPS(texture_coord, pixel_coord, offset, edges_texture, area_texture, search_texture, vec4(0.f));
}
< /code>
smaa_neighbor.vert
#version 460

#include "SMAA_vert.h"

void main()
{
set_gl_Position_and_texture_coord();
SMAANeighborhoodBlendingVS(texture_coord, offset[0]);
}
< /code>
smaa_neighbor.frag
#version 460

#include "SMAA_frag.h"

layout(binding = 0) uniform sampler2D original_image;
layout(binding = 4) uniform sampler2D blend_texture;

void main()
{
color = SMAANeighborhoodBlendingPS(texture_coord, offset[0], original_image, blend_texture);
}
< /code>
Шейдеры Используются для тестирования, не связанного с нитизациями. Треугольник по часовой стрелке вращается 45 градусов.#version 460

vec2 vertices[] =
{
{ 0, -.5 },
{ .5, .5 },
{ -.5, .5 },
};

mat2 rotate(float degree)
{
return mat2
(
cos(degree), sin(degree),
-sin(degree), cos(degree)
);
}

void main()
{
gl_Position = vec4(rotate(45) * vertices[gl_VertexIndex], 0, 1);
}
< /code>
triangle.frag
#version 460

layout(location = 0) out vec4 color;

void main()
{
color = vec4(1, 1, 1, 1);
}
< /code>
main.cpp, который содержит весь код, который нам необходимо проверить программу. < /p>
Используйте SDL3 и базовую инициализацию Vulkan и рендеринг, а также VMA для выделения памяти. < /p>
Все внешние библиотеки могут найти в cmakelists.txt. Контекст кода не может содержать здесь из -за ограничения текста. Таким образом, вы можете найти весь код на репоми-тестировании, который имеет все вулканский код итализации и другие. Здесь я только поместил код Nessessory.// structure
struct Image
{
VkImage handle;
VkImageView view;
VmaAllocation allocation;
VkFormat format;
VkExtent3D extent;
};

struct Buffer
{
VkBuffer handle;
VmaAllocation allocation;
};

struct PushConstant
{
glm::vec4 smaa_rt_metrics;
};

struct Frame
{
VkCommandBuffer cmd;
VkFence fence;
VkSemaphore image_available;
VkSemaphore render_finished;
};

// global variables
std::vector g_frames;
uint32_t g_frame_index = 0;

VmaAllocator g_allocator;
VkDevice g_device;
VkFormat g_swapchain_image_format;
VkExtent2D g_swapchain_extent;
VkCommandPool g_command_pool;
// every pass output image
Image g_source_image; // original image
Image g_edges_image; // edge detection
Image g_blend_image; // weight blend
Image g_output_image; // neighbor
VkSampler g_sampler; // linear sampler
VkDescriptorPool g_descriptor_pool;
VkDescriptorSetLayout g_descriptor_set_layout;
VkDescriptorSet g_descriptor_set;
// use for blend weight pass
Image g_area_texture;
Image g_search_texture;

std::vector g_pipelines(4); // 0 : triangle, 1 : edge detection, 2 : blend weight, 3 : neighbor
VkPipelineLayout g_pipeline_layout_SMAA; // all SMAA pass use common pipeline layout

auto create_image(VkFormat format, VkExtent2D extent, VkImageUsageFlags usage)
{
Image image
{
.format = format,
.extent = { extent.width, extent.height, 1 },
};

VkImageCreateInfo image_info
{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = image.format,
.extent = image.extent,
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = usage,
};

VmaAllocationCreateInfo alloc_info
{
.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
.usage = VMA_MEMORY_USAGE_AUTO,
};
check_vk(vmaCreateImage(g_allocator, &image_info, &alloc_info, &image.handle, &image.allocation, nullptr));

VkImageViewCreateInfo image_view_info
{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = image.handle,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = image.format,
.subresourceRange =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1,
},
};
check_vk(vkCreateImageView(g_device, &image_view_info, nullptr, &image.view));

return image;
}

void create_SMAA_images()
{
g_source_image = create_image(g_swapchain_image_format, g_swapchain_extent, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
g_edges_image = create_image(g_swapchain_image_format, g_swapchain_extent, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
g_blend_image = create_image(g_swapchain_image_format, g_swapchain_extent, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
g_output_image = create_image(g_swapchain_image_format, g_swapchain_extent, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
}

void create_sampler()
{
VkSamplerCreateInfo sampler_info
{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = VK_FILTER_LINEAR,
.minFilter = VK_FILTER_LINEAR,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
};
check_vk(vkCreateSampler(g_device, &sampler_info, nullptr, &g_sampler));
}

void create_descriptor_resource()
{
// create descriptor pool
VkDescriptorPoolSize pool_size
{
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 5,
};
VkDescriptorPoolCreateInfo pool_info
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = 1,
.poolSizeCount = 1,
.pPoolSizes = &pool_size,
};
check_vk(vkCreateDescriptorPool(g_device, &pool_info, nullptr, &g_descriptor_pool));

// create descriptor set layout
VkDescriptorSetLayoutBinding bindings[5]
{
{ .binding = 0, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT },
{ .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT },
{ .binding = 2, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT },
{ .binding = 3, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT },
{ .binding = 4, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT },
};
VkDescriptorSetLayoutCreateInfo layout_info
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 5,
.pBindings = bindings,
};
check_vk(vkCreateDescriptorSetLayout(g_device, &layout_info, nullptr, &g_descriptor_set_layout));

// allocate descriptor set
VkDescriptorSetAllocateInfo alloc_info
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = g_descriptor_pool,
.descriptorSetCount = 1,
.pSetLayouts = &g_descriptor_set_layout,
};
check_vk(vkAllocateDescriptorSets(g_device, &alloc_info, &g_descriptor_set));

// update descriptor set
std::vector image_infos
{
{ .sampler = g_sampler, .imageView = g_source_image.view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
{ .sampler = g_sampler, .imageView = g_edges_image.view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
{ .sampler = g_sampler, .imageView = g_area_texture.view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
{ .sampler = g_sampler, .imageView = g_search_texture.view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
{ .sampler = g_sampler, .imageView = g_blend_image.view, .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL },
};
std::vector write_infos(5);
for (size_t i = 0; i < image_infos.size(); ++i)
{
write_infos =
{
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = g_descriptor_set,
.dstBinding = static_cast(i),
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImageInfo = &image_infos,
};
}
vkUpdateDescriptorSets(g_device, static_cast(write_infos.size()), write_infos.data(), 0, nullptr);
}

void create_SMAA_pipeline_layout()
{
VkPushConstantRange push_constant_range
{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
.size = sizeof(PushConstant),
};
VkPipelineLayoutCreateInfo layout_info
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 1,
.pSetLayouts = &g_descriptor_set_layout,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &push_constant_range,
};
check_vk(vkCreatePipelineLayout(g_device, &layout_info, nullptr, &g_pipeline_layout_SMAA));
}

auto create_buffer(uint32_t size, VkBufferUsageFlags usages, VmaAllocationCreateFlags flags)
{
Buffer buffer;

VkBufferCreateInfo buf_info
{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.usage = usages,
};
VmaAllocationCreateInfo alloc_info
{
.flags = flags,
.usage = VMA_MEMORY_USAGE_AUTO,
};
check_vk(vmaCreateBuffer(g_allocator, &buf_info, &alloc_info, &buffer.handle, &buffer.allocation, nullptr));

return buffer;
}

void transform_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout old_layout, VkImageLayout new_layout)
{
VkImageMemoryBarrier barrier
{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.oldLayout = old_layout,
.newLayout = new_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 },
};
vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
}

auto destroy(Buffer& buffer)
{
assert(buffer.handle && buffer.allocation);
vmaDestroyBuffer(g_allocator, buffer.handle, buffer.allocation);
buffer = {};
}

void load_textures()
{
// create texture images
g_area_texture = create_image(VK_FORMAT_R8G8_UNORM, { AREATEX_WIDTH, AREATEX_HEIGHT }, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
g_search_texture = create_image(VK_FORMAT_R8_UNORM, { SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT }, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);

// create stage buffer
auto stage_buffer = create_buffer(AREATEX_SIZE + SEARCHTEX_SIZE, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);

// copy texture data to stage buffer
check_vk(vmaCopyMemoryToAllocation(g_allocator, areaTexBytes, stage_buffer.allocation, 0, AREATEX_SIZE));
check_vk(vmaCopyMemoryToAllocation(g_allocator, searchTexBytes, stage_buffer.allocation, AREATEX_SIZE, SEARCHTEX_SIZE));

// create command buffer to record
VkCommandBuffer cmd;
VkCommandBufferAllocateInfo cmd_info
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = g_command_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = 1,
};
check_vk(vkAllocateCommandBuffers(g_device, &cmd_info, &cmd));

// begin command buffer
VkCommandBufferBeginInfo beg_info
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ,
};
vkBeginCommandBuffer(cmd, &beg_info);

// transform image layout for copy
transform_image_layout(cmd, g_area_texture.handle, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
transform_image_layout(cmd, g_search_texture.handle, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);

// copy buffer to area texture
VkBufferImageCopy2 region
{
.sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2,
.bufferOffset = 0,
.imageSubresource =
{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.layerCount = 1,
},
.imageExtent =
{
.width = AREATEX_WIDTH,
.height = AREATEX_HEIGHT,
.depth = 1,
},
};
VkCopyBufferToImageInfo2 copy_info
{
.sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2,
.srcBuffer = stage_buffer.handle,
.dstImage = g_area_texture.handle,
.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.regionCount = 1,
.pRegions = &region,
};
vkCmdCopyBufferToImage2(cmd, &copy_info);

// copy buffer to search texture
region.bufferOffset = AREATEX_SIZE;
region.imageExtent.width = SEARCHTEX_WIDTH;
region.imageExtent.height = SEARCHTEX_HEIGHT;
copy_info.dstImage = g_search_texture.handle;
vkCmdCopyBufferToImage2(cmd, &copy_info);

// transform image layout for shader read
transform_image_layout(cmd, g_area_texture.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
transform_image_layout(cmd, g_search_texture.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

// end command buffer
check_vk(vkEndCommandBuffer(cmd));

// submit command buffer
VkSubmitInfo submit_info
{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &cmd,
};
check_vk(vkQueueSubmit(g_queue, 1, &submit_info, VK_NULL_HANDLE));

// wait for queue to finish
check_vk(vkQueueWaitIdle(g_queue));

// free command buffer
vkFreeCommandBuffers(g_device, g_command_pool, 1, &cmd);

// destroy stage buffer
destroy(stage_buffer);
}

auto get_file_data(std::string_view filename)
{
std::ifstream file(filename.data(), std::ios::ate | std::ios::binary);
exit_if(!file.is_open());

auto file_size = (size_t)file.tellg();
// A SPIR-V module is defined a stream of 32bit words
auto buffer = std::vector(file_size / sizeof(uint32_t));

file.seekg(0);
file.read((char*)buffer.data(), file_size);

file.close();
return buffer;
}

auto create_shader_module(std::string_view filename)
{
auto data = get_file_data(filename);
VkShaderModuleCreateInfo shader_info
{
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = data.size() * sizeof(uint32_t),
.pCode = reinterpret_cast(data.data()),
};
VkShaderModule shader_module;
check_vk(vkCreateShaderModule(g_device, &shader_info, nullptr, &shader_module));
return shader_module;
}

auto create_pipeline(VkPipelineLayout pipeline_layout, std::string_view vertex_shader, std::string_view fragment_shader) -> VkPipeline
{
// dynamic rendering
VkPipelineRenderingCreateInfo dynamic_rendering_info
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &g_swapchain_image_format,
};

// vertex and fragment shaders
std::vector shader_stages(2);
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shader_stages[0].module = create_shader_module(vertex_shader);
shader_stages[0].pName = "main";
shader_stages[1] = shader_stages[0];
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = create_shader_module(fragment_shader);

// rasterization state
VkPipelineRasterizationStateCreateInfo rasterization_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.lineWidth = 1.f,
};

// dynamic states
auto dynamic_states = std::vector
{
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};
VkPipelineDynamicStateCreateInfo dynamic_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = static_cast(dynamic_states.size()),
.pDynamicStates = dynamic_states.data(),
};

// misc states
VkPipelineVertexInputStateCreateInfo vertex_input_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
};
VkPipelineInputAssemblyStateCreateInfo input_assembly_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
};
VkPipelineViewportStateCreateInfo viewport_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1,
.scissorCount = 1,
};
VkPipelineMultisampleStateCreateInfo multisample_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.minSampleShading = 1.f,
};
VkPipelineDepthStencilStateCreateInfo depth_stencil_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
};
VkPipelineColorBlendAttachmentState color_blend_attachment
{
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT,
};
VkPipelineColorBlendStateCreateInfo color_blend_state
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.attachmentCount = 1,
.pAttachments = &color_blend_attachment,
};

// create pipeline
VkPipeline pipeline;
VkGraphicsPipelineCreateInfo info
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &dynamic_rendering_info,
.stageCount = static_cast(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input_state,
.pInputAssemblyState = &input_assembly_state,
.pViewportState = &viewport_state,
.pRasterizationState = &rasterization_state,
.pMultisampleState = &multisample_state,
.pDepthStencilState = &depth_stencil_state,
.pColorBlendState = &color_blend_state,
.pDynamicState = &dynamic_state,
.layout = pipeline_layout,
};
check_vk(vkCreateGraphicsPipelines(g_device, nullptr, 1, &info, nullptr, &pipeline));

// destroy shader modules
vkDestroyShaderModule(g_device, shader_stages[0].module, nullptr);
vkDestroyShaderModule(g_device, shader_stages[1].module, nullptr);

return pipeline;
}

void create_SMAA_pipelines()
{
g_pipelines[1] = create_pipeline(g_pipeline_layout_SMAA, "SMAA_edge_detection_vert.spv", "SMAA_edge_detection_frag.spv");
g_pipelines[2] = create_pipeline(g_pipeline_layout_SMAA, "SMAA_blend_weight_vert.spv", "SMAA_blend_weight_frag.spv");
g_pipelines[3] = create_pipeline(g_pipeline_layout_SMAA, "SMAA_neighbor_vert.spv", "SMAA_neighbor_frag.spv");
}

void post_processing()
{
auto frame = g_frames[g_frame_index];

// upload push constant and descriptor set
PushConstant pc
{
.smaa_rt_metrics = glm::vec4(1.f / g_swapchain_extent.width, 1.f / g_swapchain_extent.height, g_swapchain_extent.width, g_swapchain_extent.height),
};
vkCmdPushConstants(frame.cmd, g_pipeline_layout_SMAA, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pc), &pc);
vkCmdBindDescriptorSets(frame.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipeline_layout_SMAA, 0, 1, &g_descriptor_set, 0, nullptr);

// edge detection
transform_image_layout(frame.cmd, g_edges_image.handle, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
transform_image_layout(frame.cmd, g_source_image.handle, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
VkRenderingAttachmentInfo color_attachment
{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = g_edges_image.view,
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = { .color = { 0.f, 0.f, 0.f, 0.f } },
};
VkRenderingInfo rendering
{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = { {}, g_swapchain_extent },
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &color_attachment,
};
vkCmdBeginRendering(frame.cmd, &rendering);
vkCmdBindPipeline(frame.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipelines[1]);
vkCmdDraw(frame.cmd, 3, 1, 0, 0);
vkCmdEndRendering(frame.cmd);

// blend weight
transform_image_layout(frame.cmd, g_blend_image.handle, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
transform_image_layout(frame.cmd, g_edges_image.handle, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
color_attachment.imageView = g_blend_image.view;
vkCmdBeginRendering(frame.cmd, &rendering);
vkCmdBindPipeline(frame.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipelines[2]);
vkCmdDraw(frame.cmd, 3, 1, 0, 0);
vkCmdEndRendering(frame.cmd);

// neighbor
transform_image_layout(frame.cmd, g_output_image.handle, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
transform_image_layout(frame.cmd, g_blend_image.handle, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
color_attachment.imageView = g_output_image.view;
vkCmdBeginRendering(frame.cmd, &rendering);
vkCmdBindPipeline(frame.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, g_pipelines[3]);
vkCmdDraw(frame.cmd, 3, 1, 0, 0);
vkCmdEndRendering(frame.cmd);
}
< /code>
Информация о инструментах < /h3>
cmake version 3.30.0

// output of 'glslc --version'
shaderc v2023.8 v2025.1
spirv-tools v2025.1 v2022.4-695-gf289d047
glslang 11.1.0-1194-g8b822ee8

Target: SPIR-V 1.0

// os and other
Windows 10.0.19045, architecture 64bit
Compiler clang 18.1.8
vulkan version 1.4.309.
< /code>
внешние библиотеки < /h3>
https://github.com/libsdl-org/SDL release-3.2.12
https://github.com/GPUOpen-LibrariesAnd ... ocator.git v3.2.1
https://github.com/iryoku/smaa.git master
< /code>

Все текстуры могут видеть в renderdoc < /p>
< /blockquote>

Редактировать: я обнаружил одну проблему - текстура края была перевернута, потому что y down в Вулькане. Я исправил это, добавив `#define smaa_flip_y 0 '. Тем не менее, текстура смеси все еще выглядит странной, и конечное выходное изображение тоже неверно.

Подробнее здесь: https://stackoverflow.com/questions/796 ... is-unclear
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»