| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- /*
- * Copyright 2021 Richard Schubert. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- *
- * AMD FidelityFX Super Resolution 1.0 (FSR)
- * Based on https://github.com/GPUOpen-Effects/FidelityFX-FSR/blob/master/sample/
- */
- #include "fsr.h"
- #include <bgfx_utils.h>
- struct FsrResources
- {
- void init(uint32_t _width, uint32_t _height)
- {
- resize(_width, _height);
- // Create uniforms for screen passes and models
- m_uniforms.init();
- // Create texture sampler uniforms (used when we bind textures)
- s_inputTexture = bgfx::createUniform("InputTexture", bgfx::UniformType::Sampler);
- // Create program from shaders.
- m_bilinear32Program = bgfx::createProgram(loadShader("cs_fsr_bilinear_32"), true);
- m_easu32Program = bgfx::createProgram(loadShader("cs_fsr_easu_32"), true);
- m_rcas32Program = bgfx::createProgram(loadShader("cs_fsr_rcas_32"), true);
- m_support16BitPrecision = (bgfx::getRendererType() != bgfx::RendererType::OpenGL);
- if (m_support16BitPrecision)
- {
- m_bilinear16Program = bgfx::createProgram(loadShader("cs_fsr_bilinear_16"), true);
- m_easu16Program = bgfx::createProgram(loadShader("cs_fsr_easu_16"), true);
- m_rcas16Program = bgfx::createProgram(loadShader("cs_fsr_rcas_16"), true);
- }
- }
- void destroy()
- {
- if (m_support16BitPrecision)
- {
- bgfx::destroy(m_bilinear16Program);
- m_bilinear16Program = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_easu16Program);
- m_easu16Program = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_rcas16Program);
- m_rcas16Program = BGFX_INVALID_HANDLE;
- }
- bgfx::destroy(m_bilinear32Program);
- m_bilinear32Program = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_easu32Program);
- m_easu32Program = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_rcas32Program);
- m_rcas32Program = BGFX_INVALID_HANDLE;
- m_uniforms.destroy();
- bgfx::destroy(s_inputTexture);
- s_inputTexture = BGFX_INVALID_HANDLE;
- if (bgfx::isValid(m_easuTexture16F) )
- {
- bgfx::destroy(m_easuTexture16F);
- m_easuTexture16F = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_rcasTexture16F);
- m_rcasTexture16F = BGFX_INVALID_HANDLE;
- }
- if (bgfx::isValid(m_easuTexture32F) )
- {
- bgfx::destroy(m_easuTexture32F);
- m_easuTexture32F = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_rcasTexture32F);
- m_rcasTexture32F = BGFX_INVALID_HANDLE;
- }
- }
- void resize(uint32_t _width, uint32_t _height)
- {
- m_width = _width;
- m_height = _height;
- if (bgfx::isValid(m_easuTexture16F) )
- {
- bgfx::destroy(m_easuTexture16F);
- m_easuTexture16F = BGFX_INVALID_HANDLE;
- bgfx::destroy(m_rcasTexture16F);
- m_rcasTexture16F = BGFX_INVALID_HANDLE;
- }
- if (bgfx::isValid(m_easuTexture32F) )
- {
- bgfx::destroy(m_easuTexture32F);
- bgfx::destroy(m_rcasTexture32F);
- }
- if (m_support16BitPrecision)
- {
- m_easuTexture16F = bgfx::createTexture2D(
- uint16_t(m_width)
- , uint16_t(m_height)
- , false
- , 1
- , bgfx::TextureFormat::RGBA16F
- , BGFX_TEXTURE_COMPUTE_WRITE | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP
- );
- bgfx::setName(m_easuTexture16F, "easuTexture16F");
- m_rcasTexture16F = bgfx::createTexture2D(
- uint16_t(m_width)
- , uint16_t(m_height)
- , false
- , 1
- , bgfx::TextureFormat::RGBA16F
- , BGFX_TEXTURE_COMPUTE_WRITE | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP
- );
- bgfx::setName(m_rcasTexture16F, "rcasTexture16F");
- }
- m_easuTexture32F = bgfx::createTexture2D(
- uint16_t(m_width)
- , uint16_t(m_height)
- , false
- , 1
- , bgfx::TextureFormat::RGBA32F
- , BGFX_TEXTURE_COMPUTE_WRITE | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP
- );
- bgfx::setName(m_easuTexture32F, "easuTexture32F");
- m_rcasTexture32F = bgfx::createTexture2D(
- uint16_t(m_width)
- , uint16_t(m_height)
- , false
- , 1
- , bgfx::TextureFormat::RGBA32F
- , BGFX_TEXTURE_COMPUTE_WRITE | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP
- );
- bgfx::setName(m_rcasTexture32F, "rcasTexture32F");
- }
- struct Uniforms
- {
- struct Vec4
- {
- float x;
- float y;
- float z;
- float w;
- };
- enum
- {
- NumVec4 = 3
- };
- void init()
- {
- u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
- };
- void submit() const
- {
- bgfx::setUniform(u_params, m_params, NumVec4);
- }
- void destroy()
- {
- bgfx::destroy(u_params);
- }
- union
- {
- struct
- {
- Vec4 ViewportSizeRcasAttenuation;
- Vec4 SrcSize;
- Vec4 DstSize;
- };
- uint32_t m_params[NumVec4 * 4];
- };
- bgfx::UniformHandle u_params = BGFX_INVALID_HANDLE;
- };
- uint32_t m_width = 0;
- uint32_t m_height = 0;
- bool m_support16BitPrecision = false;
- // Resource handles
- bgfx::ProgramHandle m_bilinear16Program = BGFX_INVALID_HANDLE;
- bgfx::ProgramHandle m_easu16Program = BGFX_INVALID_HANDLE;
- bgfx::ProgramHandle m_rcas16Program = BGFX_INVALID_HANDLE;
- bgfx::TextureHandle m_easuTexture16F = BGFX_INVALID_HANDLE;
- bgfx::TextureHandle m_rcasTexture16F = BGFX_INVALID_HANDLE;
- bgfx::ProgramHandle m_bilinear32Program = BGFX_INVALID_HANDLE;
- bgfx::ProgramHandle m_easu32Program = BGFX_INVALID_HANDLE;
- bgfx::ProgramHandle m_rcas32Program = BGFX_INVALID_HANDLE;
- bgfx::TextureHandle m_easuTexture32F = BGFX_INVALID_HANDLE;
- bgfx::TextureHandle m_rcasTexture32F = BGFX_INVALID_HANDLE;
- // Shader uniforms
- Uniforms m_uniforms;
- // Uniforms to indentify texture samplers
- bgfx::UniformHandle s_inputTexture = BGFX_INVALID_HANDLE;
- };
- Fsr::Fsr()
- {
- m_resources = new FsrResources();
- }
- Fsr::~Fsr()
- {
- delete m_resources;
- }
- void Fsr::init(uint32_t _width, uint32_t _height)
- {
- m_resources->init(_width, _height);
- }
- void Fsr::destroy()
- {
- m_resources->destroy();
- }
- void Fsr::resize(uint32_t _width, uint32_t _height)
- {
- m_resources->resize(_width, _height);
- }
- bgfx::ViewId Fsr::computeFsr(bgfx::ViewId _pass, bgfx::TextureHandle _colorTexture)
- {
- updateUniforms();
- bgfx::ViewId view = _pass;
- // This value is the image region dimension that each thread group of the FSR shader operates on
- constexpr int threadGroupWorkRegionDim = 16;
- const int32_t dispatchX = (m_resources->m_width + (threadGroupWorkRegionDim - 1) ) / threadGroupWorkRegionDim;
- const int32_t dispatchY = (m_resources->m_height + (threadGroupWorkRegionDim - 1) ) / threadGroupWorkRegionDim;
- bgfx::TextureFormat::Enum const format = m_config.m_fsr16Bit
- ? bgfx::TextureFormat::RGBA16F
- : bgfx::TextureFormat::RGBA32F
- ;
- bgfx::TextureHandle fsrEasuTexture = m_config.m_fsr16Bit
- ? m_resources->m_easuTexture16F
- : m_resources->m_easuTexture32F
- ;
- // EASU pass (upscale)
- {
- bgfx::ProgramHandle program = m_config.m_fsr16Bit
- ? m_resources->m_easu16Program
- : m_resources->m_easu32Program
- ;
- if (!m_config.m_applyFsr)
- {
- program = m_resources->m_bilinear32Program;
- }
- bgfx::setViewName(view, "fsr easu");
- m_resources->m_uniforms.submit();
- bgfx::setTexture(0, m_resources->s_inputTexture, _colorTexture);
- bgfx::setImage(1, fsrEasuTexture, 0, bgfx::Access::Write, format);
- bgfx::dispatch(view, program, dispatchX, dispatchY, 1);
- ++view;
- }
- // RCAS pass (sharpening)
- if (m_config.m_applyFsrRcas)
- {
- bgfx::ProgramHandle program = m_config.m_fsr16Bit
- ? m_resources->m_rcas16Program
- : m_resources->m_rcas32Program
- ;
- bgfx::setViewName(view, "fsr rcas");
- m_resources->m_uniforms.submit();
- bgfx::setTexture(0, m_resources->s_inputTexture, fsrEasuTexture);
- bgfx::setImage(
- 1
- , m_config.m_fsr16Bit? m_resources->m_rcasTexture16F: m_resources->m_rcasTexture32F
- , 0
- , bgfx::Access::Write
- , format
- );
- bgfx::dispatch(view, program, dispatchX, dispatchY, 1);
- ++view;
- }
- return view;
- }
- bgfx::TextureHandle Fsr::getResultTexture() const
- {
- if (m_config.m_applyFsr && m_config.m_applyFsrRcas)
- {
- return m_config.m_fsr16Bit
- ? m_resources->m_rcasTexture16F
- : m_resources->m_rcasTexture32F
- ;
- }
- return m_config.m_fsr16Bit
- ? m_resources->m_easuTexture16F
- : m_resources->m_easuTexture32F
- ;
- }
- bool Fsr::supports16BitPrecision() const
- {
- return m_resources->m_support16BitPrecision;
- }
- void Fsr::updateUniforms()
- {
- const float srcWidth = float(m_resources->m_width) / m_config.m_superSamplingFactor;
- const float srcHeight = float(m_resources->m_height) / m_config.m_superSamplingFactor;
- m_resources->m_uniforms.ViewportSizeRcasAttenuation.x = srcWidth;
- m_resources->m_uniforms.ViewportSizeRcasAttenuation.y = srcHeight;
- m_resources->m_uniforms.ViewportSizeRcasAttenuation.z = m_config.m_rcasAttenuation;
- m_resources->m_uniforms.SrcSize.x = float(m_resources->m_width);
- m_resources->m_uniforms.SrcSize.y = float(m_resources->m_height);
- m_resources->m_uniforms.DstSize.x = float(m_resources->m_width);
- m_resources->m_uniforms.DstSize.y = float(m_resources->m_height);
- }
|