This commit is contained in:
butters dousha 2023-02-23 16:07:11 -05:00 committed by GitHub
commit 371b4ee2ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 22856 additions and 0 deletions

View File

@ -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.

View File

@ -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")

File diff suppressed because it is too large Load Diff

123
src/VK/offscreen/helper.hpp Normal file
View 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;
};
}

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

102
src/VK/offscreen/main.cpp Normal file
View 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;
}