Archived
1
Fork 0

Add SMAA pass

This commit is contained in:
Joshua Goins 2018-12-19 13:11:27 -05:00
parent 5b035874ab
commit 57a2ae9c0a
17 changed files with 17394 additions and 10 deletions

View file

@ -1,3 +1,4 @@
add_subdirectory(imgui) add_subdirectory(imgui)
add_subdirectory(nlohmann) add_subdirectory(nlohmann)
add_subdirectory(stb) add_subdirectory(stb)
add_subdirectory(smaa)

4
3rdparty/smaa/CMakeLists.txt vendored Executable file
View file

@ -0,0 +1,4 @@
add_library(SMAA INTERFACE)
target_include_directories(SMAA INTERFACE include)
add_library(SMAA::SMAA ALIAS SMAA)

14980
3rdparty/smaa/include/AreaTex.h vendored Executable file

File diff suppressed because it is too large Load diff

132
3rdparty/smaa/include/SearchTex.h vendored Executable file
View file

@ -0,0 +1,132 @@
/**
* Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com)
* Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
* Copyright (C) 2013 Belen Masia (bmasia@unizar.es)
* Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com)
* Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to
* do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. As clarification, there
* is no requirement that the copyright notice and permission be included in
* binary distributions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef SEARCHTEX_H
#define SEARCHTEX_H
#define SEARCHTEX_WIDTH 64
#define SEARCHTEX_HEIGHT 16
#define SEARCHTEX_PITCH SEARCHTEX_WIDTH
#define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH)
/**
* Stored in R8 format. Load it in the following format:
* - DX9: D3DFMT_L8
* - DX10: DXGI_FORMAT_R8_UNORM
*/
static const unsigned char searchTexBytes[] = {
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
#endif

View file

@ -57,7 +57,8 @@ set(GRAPH_SRC
src/animationsystem.cpp src/animationsystem.cpp
src/worldmanager.cpp src/worldmanager.cpp
src/assetmanager.cpp src/assetmanager.cpp
src/entityparser.cpp) src/entityparser.cpp
src/smaapass.cpp)
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(GRAPH_SRC set(GRAPH_SRC
@ -77,7 +78,8 @@ target_link_libraries(Graph
Vulkan::Vulkan Vulkan::Vulkan
assimp::assimp assimp::assimp
nlohmann::json nlohmann::json
stb::stb) stb::stb
SMAA::SMAA)
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_libraries(Graph target_link_libraries(Graph
@ -102,7 +104,11 @@ add_shaders(Graph
shaders/imgui.frag shaders/imgui.frag
shaders/sky.vert shaders/sky.vert
shaders/sky.frag shaders/sky.frag
shaders/shadow.vert) shaders/shadow.vert
shaders/edge.vert
shaders/edge.frag
shaders/blend.vert
shaders/blend.frag)
add_data(Graph add_data(Graph
data/suzanne.obj data/suzanne.obj

View file

@ -8,6 +8,7 @@
#include "imguipass.h" #include "imguipass.h"
#include "skypass.h" #include "skypass.h"
#include "shadowpass.h" #include "shadowpass.h"
#include "smaapass.h"
constexpr int numFrameResources = 2; constexpr int numFrameResources = 2;
@ -55,6 +56,19 @@ struct RenderTarget {
VkSemaphore renderFinishedSemaphore = nullptr; VkSemaphore renderFinishedSemaphore = nullptr;
VkFence* fences = nullptr; VkFence* fences = nullptr;
// smaa
VkImage* edgeImages = nullptr;
VkDeviceMemory* edgeMemorys = nullptr;
VkImageView* edgeImageViews = nullptr;
VkFramebuffer* edgeFramebuffers = nullptr;
VkDescriptorSet* edgeDescriptorSets = nullptr;
VkImage* blendImages = nullptr;
VkDeviceMemory* blendMemorys = nullptr;
VkImageView* blendImageViews = nullptr;
VkFramebuffer* blendFramebuffers = nullptr;
VkDescriptorSet* blendDescriptorSets = nullptr;
// imgui // imgui
VkBuffer* imguiVertexBuffers = nullptr; VkBuffer* imguiVertexBuffers = nullptr;
VkDeviceMemory* imguiVertexMemorys = nullptr; VkDeviceMemory* imguiVertexMemorys = nullptr;
@ -92,7 +106,7 @@ public:
VkShaderModule createShader(const char* path); VkShaderModule createShader(const char* path);
void uploadImageData(VkImage image, int width, int height, VkDeviceSize size, void* src); void uploadImageData(VkImage image, int width, int height, VkDeviceSize size, const void* src);
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
@ -193,4 +207,5 @@ private:
#endif #endif
SkyPass* skyPass_ = nullptr; SkyPass* skyPass_ = nullptr;
ShadowPass* shadowPass_ = nullptr; ShadowPass* shadowPass_ = nullptr;
SMAAPass* smaaPass_ = nullptr;
}; };

59
include/smaapass.h Normal file
View file

@ -0,0 +1,59 @@
#pragma once
#include <vulkan/vulkan.h>
class Renderer;
struct RenderTarget;
class SMAAPass {
public:
SMAAPass(Renderer& renderer);
~SMAAPass();
void render(VkCommandBuffer commandBuffer, RenderTarget* target);
void createDescriptorSets(RenderTarget* target);
VkRenderPass getEdgeRenderPass() const {
return edgeRenderPass;
}
VkRenderPass getBlendRenderPass() const {
return blendRenderPass;
}
private:
void loadResources();
void setupDescriptorLayouts();
void createOffscreenResources();
void createRenderPasses();
void createPipelines();
VkImage areaImage;
VkDeviceMemory areaMemory;
VkImageView areaImageView;
VkSampler areaSampler;
VkImage searchImage;
VkDeviceMemory searchMemory;
VkImageView searchImageView;
VkSampler searchSampler;
VkSampler edgeSampler;
VkSampler blendSampler;
VkRenderPass edgeRenderPass, blendRenderPass;
// edge
VkDescriptorSetLayout edgeDescriptorSetLayout;
VkPipelineLayout edgePipelineLayout;
VkPipeline edgePipeline;
// blend
VkDescriptorSetLayout blendDescriptorSetLayout;
VkPipelineLayout blendPipelineLayout;
VkPipeline blendPipeline;
Renderer& renderer;
};

27
shaders/blend.frag Executable file
View file

@ -0,0 +1,27 @@
#version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) in vec2 inUV;
layout(location = 1) in vec4 inOffset[3];
layout(location = 5) in vec2 inPixUV;
layout(location = 0) out vec4 outColor;
layout(binding = 0) uniform sampler2D edgeSampler;
layout(binding = 1) uniform sampler2D areaSampler;
layout(binding = 2) uniform sampler2D searchSampler;
void main() {
outColor = SMAABlendingWeightCalculationPS(inUV, inPixUV, inOffset, edgeSampler, areaSampler, searchSampler, ivec4(0));
}

24
shaders/blend.vert Executable file
View file

@ -0,0 +1,24 @@
#version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) out vec2 outUV;
layout(location = 1) out vec4 outOffset[3];
layout(location = 5) out vec2 outPixUV;
void main() {
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0 + -1.0, 0.0, 1.0);
SMAABlendingWeightCalculationVS(outUV, outPixUV, outOffset);
}

27
shaders/edge.frag Executable file
View file

@ -0,0 +1,27 @@
#version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) in vec2 inUV;
layout(location = 1) in vec4 inOffset[3];
layout(location = 0) out vec4 outColor;
layout(binding = 0) uniform sampler2D imageSampler;
layout(binding = 1) uniform sampler2D depthSampler;
void main() {
vec2 edge = SMAALumaEdgeDetectionPS(inUV, inOffset, imageSampler, depthSampler);
outColor = vec4(edge, 0.0, 1.0);
}

23
shaders/edge.vert Executable file
View file

@ -0,0 +1,23 @@
#version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) out vec2 outUV;
layout(location = 1) out vec4 outOffset[3];
void main() {
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0 + -1.0, 0.0, 1.0);
SMAAEdgeDetectionVS(outUV, outOffset);
}

View file

@ -1,6 +1,19 @@
#version 460 core #version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 0
#define SMAA_INCLUDE_PS 1
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) in vec2 inUV; layout(location = 0) in vec2 inUV;
layout(location = 1) in vec4 inOffset;
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 outColor;
@ -8,9 +21,11 @@ layout(binding = 0) uniform sampler2D sceneSampler;
layout(binding = 1) uniform sampler2D depthSampler; layout(binding = 1) uniform sampler2D depthSampler;
layout(binding = 2) uniform sampler2D nearFieldSampler; layout(binding = 2) uniform sampler2D nearFieldSampler;
layout(binding = 3) uniform sampler2D farFieldSampler; layout(binding = 3) uniform sampler2D farFieldSampler;
layout(binding = 4) uniform sampler2D blendSampler;
void main() { void main() {
vec3 sceneColor = texture(sceneSampler, inUV).rgb; vec3 sceneColor = vec3(0);
sceneColor = SMAANeighborhoodBlendingPS(inUV, inOffset, sceneSampler, blendSampler).rgb;
// alpha divide reconstruction // alpha divide reconstruction
vec3 farColor = texture(farFieldSampler, inUV).rgb / max(texture(farFieldSampler, inUV).a, 0.0001) * 0.02; vec3 farColor = texture(farFieldSampler, inUV).rgb / max(texture(farFieldSampler, inUV).a, 0.0001) * 0.02;

View file

@ -1,9 +1,24 @@
#version 460 core #version 460 core
#extension GL_GOOGLE_include_directive : enable
#define SMAA_RT_METRICS vec4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0)
#define SMAA_PRESET_ULTRA 1
#define SMAA_GLSL_4 1
#define SMAA_INCLUDE_VS 1
#define SMAA_INCLUDE_PS 0
#define SMAA_PREDICATION 1
#define SMAA_FLIP_Y 0
#include "smaa.glsl"
layout(location = 0) out vec2 outUV; layout(location = 0) out vec2 outUV;
layout(location = 1) out vec4 outOffset;
void main() { void main() {
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0 + -1.0, 0.0, 1.0); gl_Position = vec4(outUV * 2.0 + -1.0, 0.0, 1.0);
SMAANeighborhoodBlendingVS(outUV, outOffset);
} }

1407
shaders/smaa.glsl Executable file

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,11 @@ void PostPass::createDescriptorSet(RenderTarget* target) {
farFieldImageInfo.imageView = target->farFieldImageViews[i]; farFieldImageInfo.imageView = target->farFieldImageViews[i];
farFieldImageInfo.sampler = offscreenSampler_; farFieldImageInfo.sampler = offscreenSampler_;
VkDescriptorImageInfo blendImageInfo = {};
blendImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
blendImageInfo.imageView = target->blendImageViews[i];
blendImageInfo.sampler = offscreenSampler_;
VkWriteDescriptorSet sceneDescriptorWrite = {}; VkWriteDescriptorSet sceneDescriptorWrite = {};
sceneDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; sceneDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
sceneDescriptorWrite.descriptorCount = 1; sceneDescriptorWrite.descriptorCount = 1;
@ -95,11 +100,20 @@ void PostPass::createDescriptorSet(RenderTarget* target) {
farFieldDescriptorWrite.dstSet = target->postSets[i]; farFieldDescriptorWrite.dstSet = target->postSets[i];
farFieldDescriptorWrite.pImageInfo = &farFieldImageInfo; farFieldDescriptorWrite.pImageInfo = &farFieldImageInfo;
const std::array<VkWriteDescriptorSet, 4> descriptorWrites = { VkWriteDescriptorSet blendDescriptorWrite = {};
blendDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
blendDescriptorWrite.descriptorCount = 1;
blendDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
blendDescriptorWrite.dstBinding = 4;
blendDescriptorWrite.dstSet = target->postSets[i];
blendDescriptorWrite.pImageInfo = &blendImageInfo;
const std::array<VkWriteDescriptorSet, 5> descriptorWrites = {
sceneDescriptorWrite, sceneDescriptorWrite,
depthDescriptorWrite, depthDescriptorWrite,
nearFieldDescriptorWrite, nearFieldDescriptorWrite,
farFieldDescriptorWrite farFieldDescriptorWrite,
blendDescriptorWrite
}; };
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr); vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
@ -130,11 +144,18 @@ void PostPass::createDescriptorSetLayout() {
farFieldSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; farFieldSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
farFieldSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; farFieldSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 4> bindings = { VkDescriptorSetLayoutBinding blendSamplerBinding = {};
blendSamplerBinding.binding = 4;
blendSamplerBinding.descriptorCount = 1;
blendSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
blendSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 5> bindings = {
offscreenSamplerBinding, offscreenSamplerBinding,
depthSamplerBinding, depthSamplerBinding,
nearFieldSamplerBinding, nearFieldSamplerBinding,
farFieldSamplerBinding farFieldSamplerBinding,
blendSamplerBinding
}; };
VkDescriptorSetLayoutCreateInfo createInfo = {}; VkDescriptorSetLayoutCreateInfo createInfo = {};

View file

@ -36,11 +36,13 @@ Renderer::Renderer(GraphicsConfig config) : config_(config) {
imguiPass_ = new ImGuiPass(*this); imguiPass_ = new ImGuiPass(*this);
#endif #endif
skyPass_ = new SkyPass(*this); skyPass_ = new SkyPass(*this);
smaaPass_ = new SMAAPass(*this);
} }
Renderer::~Renderer() { Renderer::~Renderer() {
vkDeviceWaitIdle(device_); vkDeviceWaitIdle(device_);
delete smaaPass_;
delete skyPass_; delete skyPass_;
#ifdef DEBUG #ifdef DEBUG
delete imguiPass_; delete imguiPass_;
@ -150,6 +152,8 @@ void Renderer::render(World& world, RenderTarget* target) {
vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
smaaPass_->render(commandBuffer, target);
clearColor = {}; clearColor = {};
renderPassBeginInfo = {}; renderPassBeginInfo = {};
@ -304,6 +308,16 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
target->farFieldMemory = new VkDeviceMemory[numFrameResources]; target->farFieldMemory = new VkDeviceMemory[numFrameResources];
target->farFieldImageViews = new VkImageView[numFrameResources]; target->farFieldImageViews = new VkImageView[numFrameResources];
target->farFieldFramebuffers = new VkFramebuffer[numFrameResources]; target->farFieldFramebuffers = new VkFramebuffer[numFrameResources];
target->edgeImages = new VkImage[numFrameResources];
target->edgeMemorys = new VkDeviceMemory[numFrameResources];
target->edgeImageViews = new VkImageView[numFrameResources];
target->edgeFramebuffers = new VkFramebuffer[numFrameResources];
target->edgeDescriptorSets = new VkDescriptorSet[numFrameResources];
target->blendImages = new VkImage[numFrameResources];
target->blendMemorys = new VkDeviceMemory[numFrameResources];
target->blendImageViews = new VkImageView[numFrameResources];
target->blendFramebuffers = new VkFramebuffer[numFrameResources];
target->blendDescriptorSets = new VkDescriptorSet[numFrameResources];
target->imguiVertexBuffers = new VkBuffer[numFrameResources]; target->imguiVertexBuffers = new VkBuffer[numFrameResources];
target->imguiVertexMemorys = new VkDeviceMemory[numFrameResources]; target->imguiVertexMemorys = new VkDeviceMemory[numFrameResources];
target->imguiVertexBufferSizes = new size_t[numFrameResources]; target->imguiVertexBufferSizes = new size_t[numFrameResources];
@ -530,6 +544,120 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->farFieldFramebuffers[i]); vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->farFieldFramebuffers[i]);
} }
// edge image
{
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
imageCreateInfo.extent.width = target->extent.width;
imageCreateInfo.extent.height = target->extent.height;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vkCreateImage(device_, &imageCreateInfo, nullptr, &target->edgeImages[i]);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, target->edgeImages[i], &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(device_, &allocateInfo, nullptr, &target->edgeMemorys[i]);
vkBindImageMemory(device_, target->edgeImages[i], target->edgeMemorys[i], 0);
}
// edge image view
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = target->edgeImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->edgeImageViews[i]);
}
// edge framebuffer
{
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = smaaPass_->getEdgeRenderPass();
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &target->edgeImageViews[i];
framebufferInfo.width = target->extent.width;
framebufferInfo.height = target->extent.height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->edgeFramebuffers[i]);
}
// blend image
{
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
imageCreateInfo.extent.width = target->extent.width;
imageCreateInfo.extent.height = target->extent.height;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vkCreateImage(device_, &imageCreateInfo, nullptr, &target->blendImages[i]);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(device_, target->blendImages[i], &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(device_, &allocateInfo, nullptr, &target->blendMemorys[i]);
vkBindImageMemory(device_, target->blendImages[i], target->blendMemorys[i], 0);
}
// blend image view
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = target->blendImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(device_, &createInfo, nullptr, &target->blendImageViews[i]);
}
// blend framebuffer
{
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = smaaPass_->getBlendRenderPass();
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &target->blendImageViews[i];
framebufferInfo.width = target->extent.width;
framebufferInfo.height = target->extent.height;
framebufferInfo.layers = 1;
vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &target->blendFramebuffers[i]);
}
// imgui // imgui
{ {
target->imguiVertexBuffers[i] = nullptr; target->imguiVertexBuffers[i] = nullptr;
@ -544,6 +672,7 @@ RenderTarget* Renderer::createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTa
postPass_->createDescriptorSet(target); postPass_->createDescriptorSet(target);
dofPass_->createDescriptorSet(target); dofPass_->createDescriptorSet(target);
smaaPass_->createDescriptorSets(target);
VkCommandBufferAllocateInfo allocateInfo = {}; VkCommandBufferAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@ -890,7 +1019,7 @@ VkShaderModule Renderer::createShader(const char* path) {
return shaderModule; return shaderModule;
} }
void Renderer::uploadImageData(VkImage image, int width, int height, VkDeviceSize size, void* src) { void Renderer::uploadImageData(VkImage image, int width, int height, VkDeviceSize size, const void* src) {
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VkDeviceMemory stagingMemory; VkDeviceMemory stagingMemory;

499
src/smaapass.cpp Normal file
View file

@ -0,0 +1,499 @@
#include "smaapass.h"
#include <AreaTex.h>
#include <SearchTex.h>
#include "renderer.h"
SMAAPass::SMAAPass(Renderer& renderer) : renderer(renderer) {
loadResources();
setupDescriptorLayouts();
createOffscreenResources();
createRenderPasses();
createPipelines();
}
SMAAPass::~SMAAPass() {
vkDestroyPipeline(renderer.getDevice(), blendPipeline, nullptr);
vkDestroyPipeline(renderer.getDevice(), edgePipeline, nullptr);
vkDestroyPipelineLayout(renderer.getDevice(), edgePipelineLayout, nullptr);
vkDestroyPipelineLayout(renderer.getDevice(), blendPipelineLayout, nullptr);
vkDestroyRenderPass(renderer.getDevice(), edgeRenderPass, nullptr);
vkDestroyRenderPass(renderer.getDevice(), blendRenderPass, nullptr);
vkDestroySampler(renderer.getDevice(), blendSampler, nullptr);
vkDestroySampler(renderer.getDevice(), edgeSampler, nullptr);
vkDestroyDescriptorSetLayout(renderer.getDevice(), blendDescriptorSetLayout, nullptr);
vkDestroyDescriptorSetLayout(renderer.getDevice(), edgeDescriptorSetLayout, nullptr);
vkDestroySampler(renderer.getDevice(), searchSampler, nullptr);
vkDestroySampler(renderer.getDevice(), areaSampler, nullptr);
vkFreeMemory(renderer.getDevice(), searchMemory, nullptr);
vkFreeMemory(renderer.getDevice(), areaMemory, nullptr);
vkDestroyImageView(renderer.getDevice(), searchImageView, nullptr);
vkDestroyImageView(renderer.getDevice(), areaImageView, nullptr);
vkDestroyImage(renderer.getDevice(), searchImage, nullptr);
vkDestroyImage(renderer.getDevice(), areaImage, nullptr);
}
void SMAAPass::render(VkCommandBuffer commandBuffer, RenderTarget* target) {
vkCmdPipelineBarrier(commandBuffer,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_DEPENDENCY_BY_REGION_BIT,
0,
nullptr,
0,
nullptr,
0,
nullptr);
VkClearValue clearValue = {};
clearValue.color = {0.0f, 0.0f, 0.0f, 0.0f};
VkRenderPassBeginInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = edgeRenderPass;
renderPassInfo.framebuffer = target->edgeFramebuffers[target->currentResource];
renderPassInfo.renderArea.extent.width = 1280;
renderPassInfo.renderArea.extent.height = 720;
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearValue;
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, edgePipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, edgePipelineLayout, 0, 1, &target->edgeDescriptorSets[target->currentResource],
0, nullptr);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
renderPassInfo.renderPass = blendRenderPass;
renderPassInfo.framebuffer = target->blendFramebuffers[target->currentResource];
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
// TODO: add a pipeline barrier
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, blendPipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, blendPipelineLayout, 0, 1,
&target->blendDescriptorSets[target->currentResource], 0, nullptr);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
}
void SMAAPass::createDescriptorSets(RenderTarget* target) {
// TODO: colmengate these
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = renderer.getDescriptorPool();
allocInfo.descriptorSetCount = target->numImages;
// FIXME: lol what
auto layouts = new VkDescriptorSetLayout[target->numImages];
for(uint32_t i = 0; i < target->numImages; i++)
layouts[i] = edgeDescriptorSetLayout;
allocInfo.pSetLayouts = layouts;
vkAllocateDescriptorSets(renderer.getDevice(), &allocInfo, target->edgeDescriptorSets);
for(uint32_t i = 0; i < target->numImages; i++)
layouts[i] = blendDescriptorSetLayout;
vkAllocateDescriptorSets(renderer.getDevice(), &allocInfo, target->blendDescriptorSets);
for(int i = 0; i < target->numImages; i++) {
// edge
{
VkDescriptorImageInfo imageInfo = {};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = target->offscreenColorImageViews[i];
imageInfo.sampler = edgeSampler;
VkDescriptorImageInfo depthInfo = {};
depthInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
depthInfo.imageView = target->offscreenDepthImageViews[i];
depthInfo.sampler = edgeSampler;
VkWriteDescriptorSet descriptorWrites[2] = {};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = target->edgeDescriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &imageInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = target->edgeDescriptorSets[i];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &depthInfo;
vkUpdateDescriptorSets(renderer.getDevice(), 2, descriptorWrites, 0, nullptr);
}
// blend
{
VkDescriptorImageInfo edgeInfo = {};
edgeInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
edgeInfo.imageView = target->edgeImageViews[i];
edgeInfo.sampler = edgeSampler;
VkDescriptorImageInfo areaInfo = {};
areaInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
areaInfo.imageView = areaImageView;
areaInfo.sampler = areaSampler;
VkDescriptorImageInfo searchInfo = {};
searchInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
searchInfo.imageView = searchImageView;
searchInfo.sampler = searchSampler;
VkWriteDescriptorSet descriptorWrites[3] = {};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = target->blendDescriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pImageInfo = &edgeInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = target->blendDescriptorSets[i];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &areaInfo;
descriptorWrites[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[2].dstSet = target->blendDescriptorSets[i];
descriptorWrites[2].dstBinding = 2;
descriptorWrites[2].dstArrayElement = 0;
descriptorWrites[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[2].descriptorCount = 1;
descriptorWrites[2].pImageInfo = &searchInfo;
vkUpdateDescriptorSets(renderer.getDevice(), 3, descriptorWrites, 0, nullptr);
}
}
}
void SMAAPass::loadResources() {
const auto loadResource = [this](const int size, const int width, const int height, const void* data, VkFormat format, VkImage& image, VkDeviceMemory& memory, VkImageView& view) {
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = width;
imageInfo.extent.height = height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = format;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
vkCreateImage(renderer.getDevice(), &imageInfo, nullptr, &image);
VkMemoryRequirements memRequirements = {};
vkGetImageMemoryRequirements(renderer.getDevice(), image, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = renderer.findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(renderer.getDevice(), &allocInfo, nullptr, &memory);
vkBindImageMemory(renderer.getDevice(), image, memory, 0);
renderer.uploadImageData(
image,
width,
height,
size,
data);
VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = imageInfo.format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.layerCount = 1;
vkCreateImageView(renderer.getDevice(), &viewInfo, nullptr, &view);
};
loadResource(AREATEX_SIZE, AREATEX_WIDTH, AREATEX_HEIGHT, areaTexBytes, VK_FORMAT_R8G8_UNORM, areaImage, areaMemory, areaImageView);
loadResource(SEARCHTEX_SIZE, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, searchTexBytes, VK_FORMAT_R8_UNORM, searchImage, searchMemory, searchImageView);
VkSamplerCreateInfo samplerCreateInfo = {};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.addressModeV = samplerCreateInfo.addressModeU;
samplerCreateInfo.addressModeW = samplerCreateInfo.addressModeU;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.maxAnisotropy = 0;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 1.0f;
samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
vkCreateSampler(renderer.getDevice(), &samplerCreateInfo, nullptr, &areaSampler);
samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
vkCreateSampler(renderer.getDevice(), &samplerCreateInfo, nullptr, &searchSampler);
}
void SMAAPass::setupDescriptorLayouts() {
// edge
{
VkDescriptorSetLayoutBinding imageSamplerLayoutBinding = {};
imageSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
imageSamplerLayoutBinding.descriptorCount = 1;
imageSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutBinding depthSamplerLayoutBinding = {};
depthSamplerLayoutBinding.binding = 1;
depthSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
depthSamplerLayoutBinding.descriptorCount = 1;
depthSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 2> bindings = {imageSamplerLayoutBinding, depthSamplerLayoutBinding};
VkDescriptorSetLayoutCreateInfo layoutInfo = {};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = bindings.size();
layoutInfo.pBindings = bindings.data();
vkCreateDescriptorSetLayout(renderer.getDevice(), &layoutInfo, nullptr, &edgeDescriptorSetLayout);
}
// blend
{
VkDescriptorSetLayoutBinding edgeSamplerLayoutBinding = {};
edgeSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
edgeSamplerLayoutBinding.descriptorCount = 1;
edgeSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutBinding areaSamplerLayoutBinding = {};
areaSamplerLayoutBinding.binding = 1;
areaSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
areaSamplerLayoutBinding.descriptorCount = 1;
areaSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutBinding searchSamplerLayoutBinding = {};
searchSamplerLayoutBinding.binding = 2;
searchSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
searchSamplerLayoutBinding.descriptorCount = 1;
searchSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 3> bindings = {edgeSamplerLayoutBinding, areaSamplerLayoutBinding, searchSamplerLayoutBinding};
VkDescriptorSetLayoutCreateInfo layoutInfo = {};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = bindings.size();
layoutInfo.pBindings = bindings.data();
vkCreateDescriptorSetLayout(renderer.getDevice(), &layoutInfo, nullptr, &blendDescriptorSetLayout);
}
}
void SMAAPass::createOffscreenResources() {
const VkFormat colorFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
VkSamplerCreateInfo samplerCreateInfo = {};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerCreateInfo.addressModeV = samplerCreateInfo.addressModeU;
samplerCreateInfo.addressModeW = samplerCreateInfo.addressModeU;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.maxAnisotropy = 0;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = 1.0f;
samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
vkCreateSampler(renderer.getDevice(), &samplerCreateInfo, nullptr, &edgeSampler);
vkCreateSampler(renderer.getDevice(), &samplerCreateInfo, nullptr, &blendSampler);
}
void SMAAPass::createRenderPasses() {
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = VK_FORMAT_R16G16B16A16_SFLOAT;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
// FIXME: wot
vkCreateRenderPass(renderer.getDevice(), &renderPassInfo, nullptr, &edgeRenderPass);
vkCreateRenderPass(renderer.getDevice(), &renderPassInfo, nullptr, &blendRenderPass);
}
void SMAAPass::createPipelines() {
VkShaderModule edgeVertexShader = renderer.createShader("shaders/edge.vert.spv");
VkShaderModule edgeFragmentShader = renderer.createShader("shaders/edge.frag.spv");
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = edgeVertexShader;
vertShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = edgeFragmentShader;
fragShaderStageInfo.pName = "main";
VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkViewport viewport = {};
viewport.width = 1280;
viewport.height = 720;
viewport.maxDepth = 1.0f;
VkRect2D scissor = {};
scissor.extent.width = 1280;
scissor.extent.height = 720;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask =
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &edgeDescriptorSetLayout;
vkCreatePipelineLayout(renderer.getDevice(), &pipelineLayoutInfo, nullptr, &edgePipelineLayout);
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.layout = edgePipelineLayout;
pipelineInfo.renderPass = edgeRenderPass;
vkCreateGraphicsPipelines(renderer.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &edgePipeline);
VkShaderModule blendVertexShader = renderer.createShader("shaders/blend.vert.spv");
VkShaderModule blendFragmentShader = renderer.createShader("shaders/blend.frag.spv");
vertShaderStageInfo.module = blendVertexShader;
fragShaderStageInfo.module = blendFragmentShader;
VkPipelineShaderStageCreateInfo newShaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
pipelineInfo.pStages = newShaderStages;
pipelineLayoutInfo.pSetLayouts = &blendDescriptorSetLayout;
vkCreatePipelineLayout(renderer.getDevice(), &pipelineLayoutInfo, nullptr, &blendPipelineLayout);
pipelineInfo.layout = blendPipelineLayout;
pipelineInfo.renderPass = blendRenderPass;
vkCreateGraphicsPipelines(renderer.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &blendPipeline);
vkDestroyShaderModule(renderer.getDevice(), blendFragmentShader, nullptr);
vkDestroyShaderModule(renderer.getDevice(), blendVertexShader, nullptr);
vkDestroyShaderModule(renderer.getDevice(), edgeFragmentShader, nullptr);
vkDestroyShaderModule(renderer.getDevice(), edgeVertexShader, nullptr);
}