17bool VulkanRenderer::CreateTAAResources() {
18 if (m_taaResourcesCreated)
return true;
20 const VkFormat fmt = VK_FORMAT_R16G16B16A16_SFLOAT;
23 for (
int i = 0; i < 2; ++i) {
24 VkImageCreateInfo ic{};
25 ic.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
26 ic.imageType = VK_IMAGE_TYPE_2D;
27 ic.extent = { scExtent.width, scExtent.height, 1 };
31 ic.tiling = VK_IMAGE_TILING_OPTIMAL;
32 ic.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
33 ic.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
34 | VK_IMAGE_USAGE_SAMPLED_BIT
35 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
36 | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
37 ic.samples = VK_SAMPLE_COUNT_1_BIT;
38 ic.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
39 if (vkCreateImage(device, &ic,
nullptr, &m_taaImages[i]) != VK_SUCCESS)
return false;
41 VkMemoryRequirements req;
42 vkGetImageMemoryRequirements(device, m_taaImages[i], &req);
43 VkMemoryAllocateInfo alloc{};
44 alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
45 alloc.allocationSize = req.size;
46 alloc.memoryTypeIndex = FindMemoryType(req.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
47 if (vkAllocateMemory(device, &alloc,
nullptr, &m_taaMemory[i]) != VK_SUCCESS)
return false;
48 vkBindImageMemory(device, m_taaImages[i], m_taaMemory[i], 0);
50 VkImageViewCreateInfo vi{};
51 vi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
52 vi.image = m_taaImages[i];
53 vi.viewType = VK_IMAGE_VIEW_TYPE_2D;
55 vi.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
56 if (vkCreateImageView(device, &vi,
nullptr, &m_taaViews[i]) != VK_SUCCESS)
return false;
61 VkCommandBufferAllocateInfo ca{};
62 ca.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
63 ca.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
64 ca.commandPool = commands;
65 ca.commandBufferCount = 1;
66 VkCommandBuffer initCmd;
67 vkAllocateCommandBuffers(device, &ca, &initCmd);
69 VkCommandBufferBeginInfo bi{};
70 bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
71 bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
72 vkBeginCommandBuffer(initCmd, &bi);
74 VkImageSubresourceRange sr = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
75 for (
int i = 0; i < 2; ++i) {
76 VkImageMemoryBarrier bar{};
77 bar.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
78 bar.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
79 bar.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
80 bar.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
81 bar.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
82 bar.srcAccessMask = 0;
83 bar.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
84 bar.image = m_taaImages[i];
85 bar.subresourceRange = sr;
86 vkCmdPipelineBarrier(initCmd,
87 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
88 0, 0,
nullptr, 0,
nullptr, 1, &bar);
90 VkClearColorValue black{};
91 for (
int i = 0; i < 2; ++i)
92 vkCmdClearColorImage(initCmd, m_taaImages[i],
93 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &black, 1, &sr);
94 for (
int i = 0; i < 2; ++i) {
95 VkImageMemoryBarrier bar{};
96 bar.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
97 bar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
98 bar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
99 bar.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
100 bar.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
101 bar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
102 bar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
103 bar.image = m_taaImages[i];
104 bar.subresourceRange = sr;
105 vkCmdPipelineBarrier(initCmd,
106 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
107 0, 0,
nullptr, 0,
nullptr, 1, &bar);
109 vkEndCommandBuffer(initCmd);
112 sub.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
113 sub.commandBufferCount = 1;
114 sub.pCommandBuffers = &initCmd;
115 vkQueueSubmit(graphicsQueue, 1, &sub, VK_NULL_HANDLE);
116 vkQueueWaitIdle(graphicsQueue);
117 vkFreeCommandBuffers(device, commands, 1, &initCmd);
122 VkSamplerCreateInfo ss{};
123 ss.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
124 ss.magFilter = VK_FILTER_LINEAR;
125 ss.minFilter = VK_FILTER_LINEAR;
126 ss.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
127 ss.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
128 ss.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
129 ss.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
130 ss.minLod = 0.0f; ss.maxLod = 0.0f;
131 if (vkCreateSampler(device, &ss,
nullptr, &m_taaSampler) != VK_SUCCESS)
return false;
136 VkAttachmentDescription att{};
138 att.samples = VK_SAMPLE_COUNT_1_BIT;
139 att.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
140 att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
141 att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
142 att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
143 att.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
144 att.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
146 VkAttachmentReference ref{ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
147 VkSubpassDescription sub{};
148 sub.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
149 sub.colorAttachmentCount = 1;
150 sub.pColorAttachments = &ref;
152 VkSubpassDependency dep{};
153 dep.srcSubpass = VK_SUBPASS_EXTERNAL;
155 dep.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
156 dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
157 dep.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
158 dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
160 VkRenderPassCreateInfo rpi{};
161 rpi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
162 rpi.attachmentCount = 1;
163 rpi.pAttachments = &att;
164 rpi.subpassCount = 1;
165 rpi.pSubpasses = ⊂
166 rpi.dependencyCount = 1;
167 rpi.pDependencies = &dep;
168 if (vkCreateRenderPass(device, &rpi,
nullptr, &m_taaRenderPass) != VK_SUCCESS)
return false;
172 for (
int i = 0; i < 2; ++i) {
173 VkFramebufferCreateInfo fi{};
174 fi.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
175 fi.renderPass = m_taaRenderPass;
176 fi.attachmentCount = 1;
177 fi.pAttachments = &m_taaViews[i];
178 fi.width = scExtent.width;
179 fi.height = scExtent.height;
181 if (vkCreateFramebuffer(device, &fi,
nullptr, &m_taaFramebufs[i]) != VK_SUCCESS)
return false;
187 std::array<VkDescriptorSetLayoutBinding, 3> binds{};
188 for (uint32_t b = 0; b < 3; ++b) {
189 binds[b].binding = b;
190 binds[b].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
191 binds[b].descriptorCount = 1;
192 binds[b].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
194 VkDescriptorSetLayoutCreateInfo li{};
195 li.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
196 li.bindingCount =
static_cast<uint32_t
>(binds.size());
197 li.pBindings = binds.data();
198 if (vkCreateDescriptorSetLayout(device, &li,
nullptr, &m_taaInputDSL) != VK_SUCCESS)
return false;
202 VkDescriptorSetLayoutBinding b{};
204 b.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
205 b.descriptorCount = 1;
206 b.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
207 VkDescriptorSetLayoutCreateInfo li{};
208 li.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
211 if (vkCreateDescriptorSetLayout(device, &li,
nullptr, &m_taaUboDSL) != VK_SUCCESS)
return false;
216 std::array<VkDescriptorPoolSize, 2> ps{};
217 ps[0] = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3 * MAX_FRAMES_IN_FLIGHT };
218 ps[1] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 * MAX_FRAMES_IN_FLIGHT };
219 VkDescriptorPoolCreateInfo pi{};
220 pi.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
221 pi.poolSizeCount =
static_cast<uint32_t
>(ps.size());
222 pi.pPoolSizes = ps.data();
223 pi.maxSets = 2 * MAX_FRAMES_IN_FLIGHT;
224 if (vkCreateDescriptorPool(device, &pi,
nullptr, &m_taaPool) != VK_SUCCESS)
return false;
226 for (uint32_t f = 0; f < MAX_FRAMES_IN_FLIGHT; ++f) {
227 VkDescriptorSetAllocateInfo ai{};
228 ai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
229 ai.descriptorPool = m_taaPool;
230 ai.descriptorSetCount = 1;
231 ai.pSetLayouts = &m_taaInputDSL;
232 if (vkAllocateDescriptorSets(device, &ai, &m_taaInputSets[f]) != VK_SUCCESS)
return false;
234 ai.pSetLayouts = &m_taaUboDSL;
235 if (vkAllocateDescriptorSets(device, &ai, &m_taaUboSets[f]) != VK_SUCCESS)
return false;
241 const VkDeviceSize uboSize =
sizeof(TAAParams);
242 VkBufferCreateInfo bi{};
243 bi.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
245 bi.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
246 bi.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
247 for (uint32_t f = 0; f < MAX_FRAMES_IN_FLIGHT; ++f) {
248 if (vkCreateBuffer(device, &bi,
nullptr, &m_taaUboBuffers[f]) != VK_SUCCESS)
return false;
249 VkMemoryRequirements req;
250 vkGetBufferMemoryRequirements(device, m_taaUboBuffers[f], &req);
251 VkMemoryAllocateInfo alloc{};
252 alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
253 alloc.allocationSize = req.size;
254 alloc.memoryTypeIndex = FindMemoryType(req.memoryTypeBits,
255 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
256 if (vkAllocateMemory(device, &alloc,
nullptr, &m_taaUboMemory[f]) != VK_SUCCESS)
return false;
257 vkBindBufferMemory(device, m_taaUboBuffers[f], m_taaUboMemory[f], 0);
258 vkMapMemory(device, m_taaUboMemory[f], 0, uboSize, 0, &m_taaUboMapped[f]);
259 memset(m_taaUboMapped[f], 0, uboSize);
262 VkDescriptorBufferInfo dbi{ m_taaUboBuffers[f], 0, uboSize };
263 VkWriteDescriptorSet wr{};
264 wr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
265 wr.dstSet = m_taaUboSets[f];
267 wr.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
268 wr.descriptorCount = 1;
269 wr.pBufferInfo = &dbi;
270 vkUpdateDescriptorSets(device, 1, &wr, 0,
nullptr);
276 std::array<VkDescriptorSetLayout, 2> layouts{ m_taaInputDSL, m_taaUboDSL };
277 VkPipelineLayoutCreateInfo pli{};
278 pli.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
279 pli.setLayoutCount =
static_cast<uint32_t
>(layouts.size());
280 pli.pSetLayouts = layouts.data();
281 if (vkCreatePipelineLayout(device, &pli,
nullptr, &m_taaPipelineLayout) != VK_SUCCESS)
return false;
286 m_taaShader =
new VulkanShader(device);
287 if (!m_taaShader->compile(
"assets/shaders/taa.vert.spv",
288 "assets/shaders/taa.frag.spv")) {
293 VkPipelineShaderStageCreateInfo stages[] = {
294 m_taaShader->GetVertexInfo(),
295 m_taaShader->GetFragInfo()
297 VkPipelineVertexInputStateCreateInfo vin{};
298 vin.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
299 VkPipelineInputAssemblyStateCreateInfo ia{};
300 ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
301 ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
303 std::vector<VkDynamicState> dynStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
304 VkPipelineDynamicStateCreateInfo ds{};
305 ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
306 ds.dynamicStateCount =
static_cast<uint32_t
>(dynStates.size());
307 ds.pDynamicStates = dynStates.data();
309 VkPipelineViewportStateCreateInfo vps{};
310 vps.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
311 vps.viewportCount = 1; vps.scissorCount = 1;
313 VkPipelineRasterizationStateCreateInfo rs{};
314 rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
315 rs.polygonMode = VK_POLYGON_MODE_FILL;
316 rs.cullMode = VK_CULL_MODE_NONE;
319 VkPipelineMultisampleStateCreateInfo ms{};
320 ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
321 ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
323 VkPipelineDepthStencilStateCreateInfo dss{};
324 dss.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
326 VkPipelineColorBlendAttachmentState blendAtt{};
327 blendAtt.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
328 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
329 VkPipelineColorBlendStateCreateInfo cb{};
330 cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
331 cb.attachmentCount = 1;
332 cb.pAttachments = &blendAtt;
334 VkGraphicsPipelineCreateInfo gpi{};
335 gpi.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
337 gpi.pStages = stages;
338 gpi.pVertexInputState = &vin;
339 gpi.pInputAssemblyState = &ia;
340 gpi.pViewportState = &vps;
341 gpi.pRasterizationState = &rs;
342 gpi.pMultisampleState = &ms;
343 gpi.pDepthStencilState = &dss;
344 gpi.pColorBlendState = &cb;
345 gpi.pDynamicState = &ds;
346 gpi.layout = m_taaPipelineLayout;
347 gpi.renderPass = m_taaRenderPass;
349 if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &gpi,
nullptr,
350 &m_taaPipeline) != VK_SUCCESS) {
356 m_taaResourcesCreated =
true;
357 SLEAK_INFO(
"TAA resources created ({}x{})", scExtent.width, scExtent.height);
362void VulkanRenderer::CleanupTAAResources() {
363 if (!m_taaResourcesCreated)
return;
365 vkDeviceWaitIdle(device);
367 if (m_taaPipeline) { vkDestroyPipeline(device, m_taaPipeline,
nullptr); m_taaPipeline = VK_NULL_HANDLE; }
368 if (m_taaPipelineLayout) { vkDestroyPipelineLayout(device, m_taaPipelineLayout,
nullptr); m_taaPipelineLayout = VK_NULL_HANDLE; }
369 delete m_taaShader; m_taaShader =
nullptr;
371 for (
int i = 0; i < 2; ++i) {
372 if (m_taaFramebufs[i]) { vkDestroyFramebuffer(device, m_taaFramebufs[i],
nullptr); m_taaFramebufs[i] = VK_NULL_HANDLE; }
374 if (m_taaRenderPass) { vkDestroyRenderPass(device, m_taaRenderPass,
nullptr); m_taaRenderPass = VK_NULL_HANDLE; }
376 if (m_taaPool) { vkDestroyDescriptorPool(device, m_taaPool,
nullptr); m_taaPool = VK_NULL_HANDLE; }
377 if (m_taaInputDSL) { vkDestroyDescriptorSetLayout(device, m_taaInputDSL,
nullptr); m_taaInputDSL = VK_NULL_HANDLE; }
378 if (m_taaUboDSL) { vkDestroyDescriptorSetLayout(device, m_taaUboDSL,
nullptr); m_taaUboDSL = VK_NULL_HANDLE; }
380 for (uint32_t f = 0; f < MAX_FRAMES_IN_FLIGHT; ++f) {
381 if (m_taaUboMapped[f]) { vkUnmapMemory(device, m_taaUboMemory[f]); m_taaUboMapped[f] =
nullptr; }
382 if (m_taaUboBuffers[f]) { vkDestroyBuffer(device, m_taaUboBuffers[f],
nullptr); m_taaUboBuffers[f] = VK_NULL_HANDLE; }
383 if (m_taaUboMemory[f]) { vkFreeMemory(device, m_taaUboMemory[f],
nullptr); m_taaUboMemory[f] = VK_NULL_HANDLE; }
386 if (m_taaSampler) { vkDestroySampler(device, m_taaSampler,
nullptr); m_taaSampler = VK_NULL_HANDLE; }
388 for (
int i = 0; i < 2; ++i) {
389 if (m_taaViews[i]) { vkDestroyImageView(device, m_taaViews[i],
nullptr); m_taaViews[i] = VK_NULL_HANDLE; }
390 if (m_taaImages[i]) { vkDestroyImage(device, m_taaImages[i],
nullptr); m_taaImages[i] = VK_NULL_HANDLE; }
391 if (m_taaMemory[i]) { vkFreeMemory(device, m_taaMemory[i],
nullptr); m_taaMemory[i] = VK_NULL_HANDLE; }
394 m_taaResourcesCreated =
false;
398void VulkanRenderer::UpdateTAAUBO() {
399 if (!m_taaResourcesCreated || !m_taaUboMapped[currentFrame])
return;
403 MatMul4(m_cachedView, m_cachedProjection, currentVP);
405 float invCurrentVP[16];
407 memset(invCurrentVP, 0,
sizeof(invCurrentVP));
408 for (
int i = 0; i < 4; ++i) invCurrentVP[i * 4 + i] = 1.0f;
412 memcpy(p.InvCurrentVP, invCurrentVP,
sizeof(p.InvCurrentVP));
413 memcpy(p.PrevVP, m_prevViewProj,
sizeof(p.PrevVP));
414 p.ScreenW =
static_cast<float>(scExtent.width);
415 p.ScreenH =
static_cast<float>(scExtent.height);
417 p.BlendFactor = (m_taaFrameIdx <= 1) ? 1.0f : 0.1f;
420 memcpy(m_taaUboMapped[currentFrame], &p,
sizeof(p));
423 memcpy(m_prevViewProj, currentVP,
sizeof(m_prevViewProj));
427void VulkanRenderer::RenderTAAPass() {
430 const uint32_t writeIdx =
static_cast<uint32_t
>(m_taaFrameIdx % 2);
431 const uint32_t readIdx = 1u - writeIdx;
436 VkImageMemoryBarrier depBar{};
437 depBar.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
438 depBar.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
439 depBar.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
440 depBar.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
441 depBar.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
442 depBar.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
443 depBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
444 depBar.image = depthImage;
445 depBar.subresourceRange = { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 };
446 vkCmdPipelineBarrier(command,
447 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
448 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
449 0, 0,
nullptr, 0,
nullptr, 1, &depBar);
454 VkImageMemoryBarrier bar{};
455 bar.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
456 bar.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
457 bar.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
458 bar.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
459 bar.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
460 bar.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
461 bar.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
462 bar.image = m_taaImages[writeIdx];
463 bar.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
464 vkCmdPipelineBarrier(command,
465 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
466 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
467 0, 0,
nullptr, 0,
nullptr, 1, &bar);
475 VkDescriptorImageInfo infos[3]{};
476 infos[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
477 infos[0].imageView = m_hdrSceneView;
478 infos[0].sampler = m_taaSampler;
479 infos[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
480 infos[1].imageView = m_taaViews[readIdx];
481 infos[1].sampler = m_taaSampler;
482 infos[2].imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
483 infos[2].imageView = depthImageView;
484 infos[2].sampler = m_taaSampler;
486 VkWriteDescriptorSet writes[3]{};
487 for (
int b = 0; b < 3; ++b) {
488 writes[b].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
489 writes[b].dstSet = m_taaInputSets[currentFrame];
490 writes[b].dstBinding =
static_cast<uint32_t
>(b);
491 writes[b].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
492 writes[b].descriptorCount = 1;
493 writes[b].pImageInfo = &infos[b];
495 vkUpdateDescriptorSets(device, 3, writes, 0,
nullptr);
503 VkRenderPassBeginInfo rp{};
504 rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
505 rp.renderPass = m_taaRenderPass;
506 rp.framebuffer = m_taaFramebufs[writeIdx];
507 rp.renderArea.offset = { 0, 0 };
508 rp.renderArea.extent = scExtent;
509 rp.clearValueCount = 0;
510 vkCmdBeginRenderPass(command, &rp, VK_SUBPASS_CONTENTS_INLINE);
511 FillFullscreenViewportScissor(command, scExtent);
512 vkCmdBindPipeline(command, VK_PIPELINE_BIND_POINT_GRAPHICS, m_taaPipeline);
513 VkDescriptorSet sets[2] = { m_taaInputSets[currentFrame], m_taaUboSets[currentFrame] };
514 vkCmdBindDescriptorSets(command, VK_PIPELINE_BIND_POINT_GRAPHICS,
515 m_taaPipelineLayout, 0, 2, sets, 0,
nullptr);
516 vkCmdDraw(command, 3, 1, 0, 0);
517 vkCmdEndRenderPass(command);
524 VkImageMemoryBarrier toTransfer[2]{};
525 toTransfer[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
526 toTransfer[0].oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
527 toTransfer[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
528 toTransfer[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
529 toTransfer[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
530 toTransfer[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
531 toTransfer[0].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
532 toTransfer[0].image = m_taaImages[writeIdx];
533 toTransfer[0].subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
535 toTransfer[1] = toTransfer[0];
536 toTransfer[1].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
537 toTransfer[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
538 toTransfer[1].image = m_hdrSceneImage;
540 vkCmdPipelineBarrier(command,
541 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
542 0, 0,
nullptr, 0,
nullptr, 2, toTransfer);
544 VkImageCopy region{};
545 region.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
546 region.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
547 region.extent = { scExtent.width, scExtent.height, 1 };
548 vkCmdCopyImage(command,
549 m_taaImages[writeIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
550 m_hdrSceneImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
553 VkImageMemoryBarrier toRead[2]{};
554 toRead[0] = toTransfer[0];
555 toRead[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
556 toRead[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
557 toRead[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
558 toRead[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
560 toRead[1] = toRead[0];
561 toRead[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
562 toRead[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
563 toRead[1].image = m_hdrSceneImage;
565 vkCmdPipelineBarrier(command,
566 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
567 0, 0,
nullptr, 0,
nullptr, 2, toRead);
Backend-facing rendering layer shared by the four graphics backends.
bool InvertMat4(const float M[16], float out[16])
Row-major 4x4 inverse via Gauss-Jordan elimination.
void MatMul4(const float A[16], const float B[16], float C[16])
Row-major mat4 multiply: C = A * B.
Root namespace for everything the engine exposes.