Merge 9d96967faf
into 149cf26e12
This commit is contained in:
commit
371b4ee2ec
|
@ -797,6 +797,10 @@ To build the FSR2 sample, please follow the following instructions:
|
|||
|
||||
3) Open the solutions in the DX12 or Vulkan directory (depending on your preference), compile and run.
|
||||
|
||||
4) There is an off-screen version which currently runs on Vulkan,to use this,you need to provide:
|
||||
- Color textures (RGBA)
|
||||
- Motion vectors and depth textures(RG for motion vectors and B for depth,and please remain the A channel)
|
||||
|
||||
# Limitations
|
||||
|
||||
FSR2 requires a GPU with typed UAV load and R16G16B16A16_UNORM support.
|
||||
|
|
|
@ -49,6 +49,11 @@ set(sources
|
|||
AnimatedTexture.h
|
||||
dpiawarescaling.manifest)
|
||||
|
||||
set(sources_offscreen
|
||||
./offscreen/main.cpp
|
||||
./offscreen/helper.hpp
|
||||
./offscreen/Vulkan_FSR2.hpp)
|
||||
|
||||
set(fsr1_shaders_src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../ffx-fsr2-api/shaders/ffx_core.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../ffx-fsr2-api/shaders/ffx_common_types.h
|
||||
|
@ -124,6 +129,7 @@ set(sample_shaders_src
|
|||
set(APP_ICON_GPUOPEN "${CMAKE_CURRENT_SOURCE_DIR}/../common/GpuOpenIcon.rc")
|
||||
|
||||
source_group("sources" FILES ${sources})
|
||||
source_group("sources_offscreen" FILES ${sources_offscreen})
|
||||
source_group("spatial_shaders" FILES ${fsr1_shaders_src})
|
||||
source_group("fsr2_shaders" FILES ${fsr2_shaders_src})
|
||||
source_group("particle_shaders" FILES ${particle_shaders_src})
|
||||
|
@ -146,4 +152,13 @@ target_link_directories(FSR2_Sample_VK PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../
|
|||
add_dependencies(FSR2_Sample_VK copied_vk_shaders_fsr2_src)
|
||||
|
||||
set_target_properties(FSR2_Sample_VK PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" DEBUG_POSTFIX "d")
|
||||
|
||||
add_executable(FSR2_OffScreen_VK ${sources_offscreen} ${fsr2_src} ${fsr1_shaders_src} ${fsr2_shaders_src} ${particle_shaders_src} ${spd_shaders_src} ${common} ${APP_ICON_GPUOPEN})
|
||||
target_compile_definitions(FSR2_OffScreen_VK PRIVATE $<$<CONFIG:RelWithDebInfo>:FSR2_DEBUG_SHADERS=1>)
|
||||
target_link_libraries(FSR2_OffScreen_VK LINK_PUBLIC Cauldron_VK Vulkan::Vulkan ffx_fsr2_api_x64 ffx_fsr2_api_vk_x64) # ffx_fsr2_api_x64
|
||||
target_include_directories(FSR2_OffScreen_VK PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/offscreen/include ${CMAKE_CURRENT_SOURCE_DIR}/../ffx-fsr2-api ${CMAKE_CURRENT_SOURCE_DIR}/../../libs)
|
||||
target_link_directories(FSR2_OffScreen_VK PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../libs)
|
||||
|
||||
set_target_properties(FSR2_OffScreen_VK PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" DEBUG_POSTFIX "d")
|
||||
|
||||
set_source_files_properties(${Shaders_src} PROPERTIES VS_TOOL_OVERRIDE "Text")
|
||||
|
|
1120
src/VK/offscreen/Vulkan_FSR2.hpp
Normal file
1120
src/VK/offscreen/Vulkan_FSR2.hpp
Normal file
File diff suppressed because it is too large
Load Diff
123
src/VK/offscreen/helper.hpp
Normal file
123
src/VK/offscreen/helper.hpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
#pragma once
|
||||
#define TINYEXR_IMPLEMENTATION
|
||||
#include <tinyexr.h>
|
||||
#include <FindFiles.h>
|
||||
#include <iostream>
|
||||
|
||||
struct config
|
||||
{
|
||||
std::vector<std::string> file_list;
|
||||
std::string input_path = "";
|
||||
std::string motion_depth_path = "";
|
||||
std::string out_path = "";
|
||||
float scale_motion_x = 1.0f;
|
||||
float scale_motion_y = 1.0f;
|
||||
float scale_depth = 1.0f;
|
||||
double deltaTime = 33.3f;
|
||||
int outWidth = 1;
|
||||
int outHeight = 1;
|
||||
bool reset = false;
|
||||
bool enableJitter = false;
|
||||
};
|
||||
|
||||
bool get_files(std::vector<std::string>& fileNames, std::string& input_path)
|
||||
{
|
||||
FindFiles finder;
|
||||
fileNames = finder.findFiles(input_path.c_str());
|
||||
if (fileNames.empty()) return false;
|
||||
std::sort(fileNames.begin(), fileNames.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<float> read_image_exr(const std::string& file_path, int& w, int& h,int channel)
|
||||
{
|
||||
float* data = nullptr;
|
||||
const char* err = nullptr;
|
||||
int ret = LoadEXR(&data, &w, &h, file_path.c_str(), &err);
|
||||
if (ret != TINYEXR_SUCCESS) {
|
||||
if (err) {
|
||||
std::cout << "EXR reading error: " << err << "\n";
|
||||
FreeEXRErrorMessage(err);
|
||||
}
|
||||
}
|
||||
std::vector<float> data_rgba{ data ,data+(w*h)*channel}; // auto free
|
||||
return data_rgba;
|
||||
}
|
||||
|
||||
void write_exr(const std::string& _file_path, std::vector<float> &data, int w, int h, int _channels=4,
|
||||
bool use_half = false)
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
std::string file_path = _file_path;
|
||||
|
||||
EXRHeader header;
|
||||
InitEXRHeader(&header);
|
||||
|
||||
EXRImage image;
|
||||
InitEXRImage(&image);
|
||||
|
||||
image.num_channels = _channels;
|
||||
|
||||
int pixel_n = w * h;
|
||||
std::vector<float> images[4];
|
||||
images[0].resize(pixel_n);
|
||||
images[1].resize(pixel_n);
|
||||
images[2].resize(pixel_n);
|
||||
images[3].resize(pixel_n);
|
||||
|
||||
for (int i = 0; i < pixel_n; i++) {
|
||||
images[0][i] = data[4 * i + 0];
|
||||
images[1][i] = data[4 * i + 1];
|
||||
images[2][i] = data[4 * i + 2];
|
||||
images[3][i] = data[4 * i + 3];
|
||||
}
|
||||
|
||||
float* image_ptr[4];
|
||||
image_ptr[0] = images[3].data(); // A
|
||||
image_ptr[1] = images[2].data(); // B
|
||||
image_ptr[2] = images[1].data(); // G
|
||||
image_ptr[3] = images[0].data(); // R
|
||||
|
||||
|
||||
image.images = (uint8_t**)image_ptr;
|
||||
image.width = w;
|
||||
image.height = h;
|
||||
|
||||
header.num_channels = 4;
|
||||
auto channels = std::make_unique<EXRChannelInfo[]>(header.num_channels);
|
||||
header.channels = channels.get();
|
||||
// Must be (A)BGR order, since most of EXR viewers expect this channel order
|
||||
strncpy_s(header.channels[0].name, "A", 255);
|
||||
header.channels[0].name[strlen("A")] = '\0';
|
||||
strncpy_s(header.channels[1].name, "B", 255);
|
||||
header.channels[1].name[strlen("B")] = '\0';
|
||||
strncpy_s(header.channels[2].name, "G", 255);
|
||||
header.channels[2].name[strlen("G")] = '\0';
|
||||
strncpy_s(header.channels[3].name, "R", 255);
|
||||
header.channels[3].name[strlen("R")] = '\0';
|
||||
|
||||
auto pixel_types = std::make_unique<int[]>(header.num_channels);
|
||||
header.pixel_types = pixel_types.get();
|
||||
auto requested_pixel_types = std::make_unique<int[]>(header.num_channels);
|
||||
header.requested_pixel_types = requested_pixel_types.get();
|
||||
for (int i = 0; i < header.num_channels; i++) {
|
||||
header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
|
||||
header.requested_pixel_types[i] =
|
||||
use_half ? // pixel type of output image to be stored in EXR file
|
||||
TINYEXR_PIXELTYPE_HALF :
|
||||
TINYEXR_PIXELTYPE_FLOAT;
|
||||
}
|
||||
|
||||
header.compression_type = TINYEXR_COMPRESSIONTYPE_ZIP;
|
||||
|
||||
const char* err = nullptr;
|
||||
int ret = SaveEXRImageToFile(&image, &header, file_path.c_str(), &err);
|
||||
if (ret != TINYEXR_SUCCESS) {
|
||||
if (err) {
|
||||
std::cout << "EXR writing error: " << err << std::endl;
|
||||
FreeEXRErrorMessage(err);
|
||||
}
|
||||
return;
|
||||
};
|
||||
}
|
143
src/VK/offscreen/include/FindFiles.h
Normal file
143
src/VK/offscreen/include/FindFiles.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Find and generate a file list of the folder.
|
||||
**/
|
||||
|
||||
#ifndef FIND_FILES_H
|
||||
#define FIND_FILES_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class FindFiles
|
||||
{
|
||||
public:
|
||||
FindFiles(){}
|
||||
~FindFiles(){}
|
||||
|
||||
std::vector<std::string> findFiles( const char *lpPath, const char *secName = ".*" );
|
||||
|
||||
private:
|
||||
std::vector<std::string> file_lists;
|
||||
};
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
#include <direct.h>
|
||||
|
||||
std::vector<std::string> FindFiles::findFiles( const char *lpPath, const char *secName /*= ".*" */ )
|
||||
{
|
||||
char szFind[MAX_PATH];
|
||||
char szFile[MAX_PATH];
|
||||
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
|
||||
strcpy(szFind,lpPath);
|
||||
strcat(szFind,"\\*");
|
||||
strcat(szFind,secName);
|
||||
|
||||
HANDLE hFind=::FindFirstFile(szFind,&FindFileData);
|
||||
|
||||
if(INVALID_HANDLE_VALUE == hFind)
|
||||
{
|
||||
std::cout << "Empty folder!" << std::endl;
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if(FindFileData.cFileName[0]!='.')
|
||||
{
|
||||
strcpy(szFile,lpPath);
|
||||
strcat(szFile,"\\");
|
||||
strcat(szFile,FindFileData.cFileName);
|
||||
findFiles(szFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( szFile[0] )
|
||||
{
|
||||
std::string filePath = lpPath;
|
||||
filePath += "\\";
|
||||
filePath = FindFileData.cFileName;
|
||||
file_lists.push_back(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string filePath = szFile;
|
||||
filePath = FindFileData.cFileName;
|
||||
file_lists.push_back(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
}while(::FindNextFile(hFind,&FindFileData));
|
||||
|
||||
::FindClose(hFind);
|
||||
return file_lists;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <queue>
|
||||
|
||||
std::vector<std::string> FindFiles::findFiles( const char *lpPath, const char *secName /*= ".*" */ )
|
||||
{
|
||||
(void)secName;
|
||||
|
||||
std::vector<std::string> result;
|
||||
std::queue<std::string> queue;
|
||||
std::string dirname;
|
||||
|
||||
DIR *dir;
|
||||
if ( !(dir = opendir ( lpPath )) ) {
|
||||
return result;
|
||||
}
|
||||
queue.push( lpPath );
|
||||
|
||||
struct dirent *ent;
|
||||
while ( !queue.empty() )
|
||||
{
|
||||
|
||||
dirname = queue.front();
|
||||
dir = opendir( dirname.c_str() );
|
||||
queue.pop();
|
||||
if ( !dir ) { continue; }
|
||||
|
||||
while( ent = readdir( dir ) )
|
||||
{
|
||||
|
||||
if ( strcmp(".", ent->d_name) == 0 || strcmp("..", ent->d_name) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( ent->d_type == DT_DIR )
|
||||
{
|
||||
queue.push( dirname+"/"+ent->d_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back( /*dirname + "/" + */ent->d_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closedir( dir );
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // FIND_FILES_H
|
7763
src/VK/offscreen/include/stb_image.h
Normal file
7763
src/VK/offscreen/include/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
13586
src/VK/offscreen/include/tinyexr.h
Normal file
13586
src/VK/offscreen/include/tinyexr.h
Normal file
File diff suppressed because it is too large
Load Diff
102
src/VK/offscreen/main.cpp
Normal file
102
src/VK/offscreen/main.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
#include "Vulkan_FSR2.hpp"
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cout << "Usage: FSR2 OffScreen [OPTIONS]\n\n";
|
||||
std::cout << "OPTIONS:\n";
|
||||
std::cout << " --color_path <input_path> path of input color images\n";
|
||||
std::cout << " --mv_d_path <motion_depth_path> path of motion vector and depth of input images\n";
|
||||
std::cout << " --out_path <out_path> the output path of the result images\n";
|
||||
std::cout << " --s_mv_x <number> the scale of x of motion vector\n";
|
||||
std::cout << " --s_mv_y <number> the scale of y of motion vector\n";
|
||||
std::cout << " --s_depth <number> the scale of depth\n";
|
||||
std::cout << " --fps <number> Frames Per Second\n";
|
||||
std::cout << " --w <number> output Width\n";
|
||||
std::cout << " --h <number> output Height\n";
|
||||
std::cout << " --r reset for every frame\n";
|
||||
std::cout << " --j enable Jitter\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
std::vector<std::string> file_list;
|
||||
std::string input_path = "";
|
||||
std::string motion_depth_path = "";
|
||||
std::string out_path = "";
|
||||
float scale_motion_x = -0.5f;//default value cause I am working with ue4.
|
||||
float scale_motion_y = 0.5f;
|
||||
float scale_depth = 1000.0f;
|
||||
double deltaTime = 33.3f;//33.3f for 30fps, if running at 60fps, the value passed should be around 16.6f.
|
||||
float outWidth = 3840;
|
||||
float outHeight = 2160;
|
||||
bool reset = false;
|
||||
bool enableJitter = false;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--color_path") == 0 && i + 1 < argc)
|
||||
{
|
||||
input_path = argv[i + 1];
|
||||
}
|
||||
else if (strcmp(argv[i], "--mv_d_path") == 0 && i + 1 < argc)
|
||||
{
|
||||
motion_depth_path = argv[i + 1];
|
||||
}
|
||||
else if (strcmp(argv[i], "--out_path") == 0 && i + 1 < argc)
|
||||
{
|
||||
out_path = argv[i + 1];
|
||||
}
|
||||
else if (strcmp(argv[i], "--s_mv_x") == 0 && i + 1 < argc)
|
||||
{
|
||||
scale_motion_x = atof(argv[i + 1]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--s_mv_y") == 0 && i + 1 < argc)
|
||||
{
|
||||
scale_motion_y = atof(argv[i + 1]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--s_depth") == 0 && i + 1 < argc)
|
||||
{
|
||||
scale_depth = atof(argv[i + 1]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--fps") == 0 && i + 1 < argc)
|
||||
{
|
||||
double fps = atof(argv[i + 1]);
|
||||
deltaTime = 1.0f / fps;
|
||||
}
|
||||
else if (strcmp(argv[i], "--w") == 0 && i + 1 < argc)
|
||||
{
|
||||
outWidth = atoi(argv[i + 1]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--h") == 0 && i + 1 < argc)
|
||||
{
|
||||
outHeight = atoi(argv[i + 1]);
|
||||
}
|
||||
else if (strcmp(argv[i], "--r") == 0)
|
||||
{
|
||||
reset = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "--j") == 0)
|
||||
{
|
||||
enableJitter = true;
|
||||
}
|
||||
}
|
||||
get_files(file_list, input_path);
|
||||
//copy
|
||||
config config_fsr;
|
||||
config_fsr.file_list = file_list;
|
||||
config_fsr.input_path = input_path;
|
||||
config_fsr.motion_depth_path = motion_depth_path;
|
||||
config_fsr.out_path = out_path;
|
||||
config_fsr.scale_motion_x = scale_motion_x;
|
||||
config_fsr.scale_motion_y = scale_motion_y;
|
||||
config_fsr.scale_depth = scale_depth;
|
||||
config_fsr.deltaTime = deltaTime;
|
||||
config_fsr.outWidth = outWidth;
|
||||
config_fsr.outHeight = outHeight;
|
||||
config_fsr.reset = reset;
|
||||
config_fsr.enableJitter = enableJitter;
|
||||
|
||||
Vulkan_FSR2 FSR2;
|
||||
FSR2.run(config_fsr);
|
||||
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user