fix: 修复超分scaling=1时黑屏问题,确认超分模块在nouveau驱动环境下无法正确运行问题
- 添加参数检查,当scaling<=1时自动关闭超分并WARN - 添加运行环境提示,当渲染器处于nouveau驱动环境中时自动关闭超分并WARNmain
parent
9259bb9c6f
commit
5bb7d461a4
Binary file not shown.
|
|
@ -115,9 +115,9 @@ private:
|
||||||
SuperResolutionConfig config_;
|
SuperResolutionConfig config_;
|
||||||
uint current_jitter_frame_;
|
uint current_jitter_frame_;
|
||||||
|
|
||||||
TextureHandle low_res_rt_texture_; // W/block × H/block – per-frame RT output
|
TextureHandle low_res_rt_texture_; // W/block × H/block – per-frame RT output
|
||||||
TextureHandle accumulated_rt_texture_; // W × H – running average (binding 4)
|
TextureHandle accumulated_rt_texture_; // W × H – running average (binding 4)
|
||||||
TextureHandle upscaled_texture_; // W × H – final tonemapped output
|
TextureHandle upscaled_texture_; // W × H – final tonemapped output
|
||||||
|
|
||||||
std::shared_ptr<Shader> compute_shader_;
|
std::shared_ptr<Shader> compute_shader_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
|
||||||
|
|
@ -7,142 +7,146 @@
|
||||||
namespace are {
|
namespace are {
|
||||||
|
|
||||||
Denoiser::Denoiser(uint width, uint height)
|
Denoiser::Denoiser(uint width, uint height)
|
||||||
: width_(width)
|
: width_(width)
|
||||||
, height_(height)
|
, height_(height)
|
||||||
, output_texture_(INVALID_HANDLE)
|
, output_texture_(INVALID_HANDLE)
|
||||||
, history_texture_(INVALID_HANDLE)
|
, history_texture_(INVALID_HANDLE)
|
||||||
, history_valid_(false)
|
, history_valid_(false)
|
||||||
, initialized_(false) {
|
, initialized_(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Denoiser::~Denoiser() {
|
Denoiser::~Denoiser() {
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Denoiser::initialize(const std::shared_ptr<Shader>& shader) {
|
bool Denoiser::initialize(const std::shared_ptr<Shader> &shader) {
|
||||||
if (initialized_) return true;
|
if (initialized_)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!shader || !shader->is_valid()) {
|
if (!shader || !shader->is_valid()) {
|
||||||
ARE_LOG_ERROR("Invalid denoise shader");
|
ARE_LOG_ERROR("Invalid denoise shader");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_ = shader;
|
shader_ = shader;
|
||||||
create_output_texture_();
|
create_output_texture_();
|
||||||
|
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
ARE_LOG_INFO("Denoiser initialized");
|
ARE_LOG_INFO("Denoiser initialized");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Denoiser::release() {
|
void Denoiser::release() {
|
||||||
if (!initialized_) return;
|
if (!initialized_)
|
||||||
|
return;
|
||||||
|
|
||||||
shader_.reset();
|
shader_.reset();
|
||||||
|
|
||||||
if (output_texture_ != INVALID_HANDLE) {
|
if (output_texture_ != INVALID_HANDLE) {
|
||||||
ResourceManager::instance().destroy_texture(output_texture_);
|
ResourceManager::instance().destroy_texture(output_texture_);
|
||||||
output_texture_ = INVALID_HANDLE;
|
output_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (history_texture_ != INVALID_HANDLE) {
|
if (history_texture_ != INVALID_HANDLE) {
|
||||||
ResourceManager::instance().destroy_texture(history_texture_);
|
ResourceManager::instance().destroy_texture(history_texture_);
|
||||||
history_texture_ = INVALID_HANDLE;
|
history_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
history_valid_ = false;
|
history_valid_ = false;
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Denoiser::resize(uint width, uint height) {
|
void Denoiser::resize(uint width, uint height) {
|
||||||
if (width == width_ && height == height_) return;
|
if (width == width_ && height == height_)
|
||||||
width_ = width;
|
return;
|
||||||
height_ = height;
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
|
||||||
if (!initialized_) return;
|
if (!initialized_)
|
||||||
|
return;
|
||||||
|
|
||||||
ResourceManager &rm = ResourceManager::instance();
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (output_texture_ != INVALID_HANDLE) {
|
if (output_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(output_texture_);
|
rm.destroy_texture(output_texture_);
|
||||||
output_texture_ = INVALID_HANDLE;
|
output_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (history_texture_ != INVALID_HANDLE) {
|
if (history_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(history_texture_);
|
rm.destroy_texture(history_texture_);
|
||||||
history_texture_ = INVALID_HANDLE;
|
history_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
history_valid_ = false;
|
history_valid_ = false;
|
||||||
create_output_texture_();
|
create_output_texture_();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle Denoiser::denoise(TextureHandle input_texture, int radius, float temporal_weight) {
|
TextureHandle Denoiser::denoise(TextureHandle input_texture, int radius, float temporal_weight) {
|
||||||
if (!initialized_) return input_texture;
|
if (!initialized_)
|
||||||
|
return input_texture;
|
||||||
|
|
||||||
radius = (radius < 0) ? 0 : radius;
|
radius = (radius < 0) ? 0 : radius;
|
||||||
temporal_weight = (temporal_weight < 0.0f) ? 0.0f : ((temporal_weight > 1.0f) ? 1.0f : temporal_weight);
|
temporal_weight = (temporal_weight < 0.0f) ? 0.0f : ((temporal_weight > 1.0f) ? 1.0f : temporal_weight);
|
||||||
|
|
||||||
shader_->use();
|
shader_->use();
|
||||||
|
|
||||||
glBindImageTexture(0, input_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
glBindImageTexture(0, input_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||||
glBindImageTexture(1, output_texture_, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
glBindImageTexture(1, output_texture_, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
||||||
|
|
||||||
shader_->set_int("u_radius", radius);
|
shader_->set_int("u_radius", radius);
|
||||||
shader_->set_float("u_temporal_weight", temporal_weight);
|
shader_->set_float("u_temporal_weight", temporal_weight);
|
||||||
shader_->set_bool("u_has_history", history_valid_ && temporal_weight > 0.0f);
|
shader_->set_bool("u_has_history", history_valid_ && temporal_weight > 0.0f);
|
||||||
|
|
||||||
// Bind history texture if available and temporal accumulation is enabled
|
// Bind history texture if available and temporal accumulation is enabled
|
||||||
if (history_valid_ && temporal_weight > 0.0f) {
|
if (history_valid_ && temporal_weight > 0.0f) {
|
||||||
glBindImageTexture(2, history_texture_, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
glBindImageTexture(2, history_texture_, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint groups_x = (width_ + COMPUTE_GROUP_SIZE_X - 1) / COMPUTE_GROUP_SIZE_X;
|
uint groups_x = (width_ + COMPUTE_GROUP_SIZE_X - 1) / COMPUTE_GROUP_SIZE_X;
|
||||||
uint groups_y = (height_ + COMPUTE_GROUP_SIZE_Y - 1) / COMPUTE_GROUP_SIZE_Y;
|
uint groups_y = (height_ + COMPUTE_GROUP_SIZE_Y - 1) / COMPUTE_GROUP_SIZE_Y;
|
||||||
glDispatchCompute(groups_x, groups_y, 1);
|
glDispatchCompute(groups_x, groups_y, 1);
|
||||||
|
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||||
|
|
||||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
// Copy output to history for next frame (if temporal accumulation is enabled)
|
||||||
|
if (temporal_weight > 0.0f) {
|
||||||
|
// Create history texture if it doesn't exist
|
||||||
|
if (history_texture_ == INVALID_HANDLE) {
|
||||||
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
TextureDescription desc;
|
||||||
|
desc.width = width_;
|
||||||
|
desc.height = height_;
|
||||||
|
desc.format = TextureFormat::RGBA32F;
|
||||||
|
desc.filter = TextureFilter::NEAREST;
|
||||||
|
desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
|
history_texture_ = rm.create_texture(desc);
|
||||||
|
}
|
||||||
|
|
||||||
// Copy output to history for next frame (if temporal accumulation is enabled)
|
// Copy output to history using GPU (blit or compute)
|
||||||
if (temporal_weight > 0.0f) {
|
// For simplicity, we'll just bind output as history for next frame
|
||||||
// Create history texture if it doesn't exist
|
// This requires double buffering - let's swap the textures
|
||||||
if (history_texture_ == INVALID_HANDLE) {
|
std::swap(output_texture_, history_texture_);
|
||||||
ResourceManager &rm = ResourceManager::instance();
|
history_valid_ = true;
|
||||||
TextureDescription desc;
|
|
||||||
desc.width = width_;
|
|
||||||
desc.height = height_;
|
|
||||||
desc.format = TextureFormat::RGBA32F;
|
|
||||||
desc.filter = TextureFilter::NEAREST;
|
|
||||||
desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
|
||||||
history_texture_ = rm.create_texture(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy output to history using GPU (blit or compute)
|
// Return the new output (which was history before swap)
|
||||||
// For simplicity, we'll just bind output as history for next frame
|
return output_texture_;
|
||||||
// This requires double buffering - let's swap the textures
|
}
|
||||||
std::swap(output_texture_, history_texture_);
|
|
||||||
history_valid_ = true;
|
|
||||||
|
|
||||||
// Return the new output (which was history before swap)
|
return output_texture_;
|
||||||
return output_texture_;
|
|
||||||
}
|
|
||||||
|
|
||||||
return output_texture_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Denoiser::reset_history() {
|
void Denoiser::reset_history() {
|
||||||
history_valid_ = false;
|
history_valid_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Denoiser::create_output_texture_() {
|
void Denoiser::create_output_texture_() {
|
||||||
ResourceManager &rm = ResourceManager::instance();
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
TextureDescription desc;
|
TextureDescription desc;
|
||||||
desc.width = width_;
|
desc.width = width_;
|
||||||
desc.height = height_;
|
desc.height = height_;
|
||||||
desc.format = TextureFormat::RGBA32F;
|
desc.format = TextureFormat::RGBA32F;
|
||||||
desc.filter = TextureFilter::NEAREST;
|
desc.filter = TextureFilter::NEAREST;
|
||||||
desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
desc.wrap = TextureWrap::CLAMP_TO_EDGE;
|
||||||
output_texture_ = rm.create_texture(desc);
|
output_texture_ = rm.create_texture(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace are
|
} // namespace are
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "core/renderer.h"
|
#include "core/renderer.h"
|
||||||
#include "resource/resource_manager.h"
|
#include "resource/resource_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -24,6 +25,27 @@ bool Renderer::initialize() {
|
||||||
|
|
||||||
ARE_LOG_INFO("Initializing Aurora Rendering Engine...");
|
ARE_LOG_INFO("Initializing Aurora Rendering Engine...");
|
||||||
|
|
||||||
|
// The parameter check for super resolution module
|
||||||
|
if (config_.sr_config.enabled) {
|
||||||
|
// Parameters checking
|
||||||
|
if (config_.sr_config.scaling <= 1) {
|
||||||
|
ARE_LOG_WARN("Super resolution disabled: scaling must be > 1 (got " + std::to_string(config_.sr_config.scaling) + ")");
|
||||||
|
config_.sr_config.enabled = false;
|
||||||
|
config_.sr_config.scaling = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The super resolution module does not support nouveau driver
|
||||||
|
std::string vendor = std::string(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
|
||||||
|
std::transform(vendor.begin(), vendor.end(), vendor.begin(), ::tolower);
|
||||||
|
std::string renderer = std::string(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
|
||||||
|
std::transform(renderer.begin(), renderer.end(), renderer.begin(), ::tolower);
|
||||||
|
if (vendor.find("mesa") != std::string::npos && renderer.find("nv") != std::string::npos) {
|
||||||
|
ARE_LOG_WARN("Super resolution disabled: The super resolution module on nouveau may produce artifacts. Please switch to the NVIDIA proprietary driver if possible.");
|
||||||
|
config_.sr_config.enabled = false;
|
||||||
|
config_.sr_config.scaling = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize shader manager
|
// Initialize shader manager
|
||||||
shader_manager_ = std::make_unique<ShaderManager>();
|
shader_manager_ = std::make_unique<ShaderManager>();
|
||||||
if (!shader_manager_->initialize()) {
|
if (!shader_manager_->initialize()) {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace are {
|
namespace are {
|
||||||
|
|
||||||
|
|
@ -24,43 +25,51 @@ SuperResolution::~SuperResolution() {
|
||||||
|
|
||||||
bool SuperResolution::initialize(const std::shared_ptr<Shader> &shader) {
|
bool SuperResolution::initialize(const std::shared_ptr<Shader> &shader) {
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
ARE_LOG_WARN("SuperResolution already initialized");
|
ARE_LOG_WARN("Super resolution already initialized");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shader || !shader->is_valid()) {
|
if (!shader || !shader->is_valid()) {
|
||||||
ARE_LOG_ERROR("Invalid shader");
|
ARE_LOG_ERROR("Invalid shader");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_shader_ = shader;
|
compute_shader_ = shader;
|
||||||
create_textures_();
|
create_textures_();
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
ARE_LOG_INFO("SuperResolution initialized: " + std::to_string(full_width_) + "x" + std::to_string(full_height_) + " scaling_px=" + std::to_string(config_.scaling) + " lowres=" + std::to_string(low_res_w_) + "x" + std::to_string(low_res_h_));
|
ARE_LOG_INFO("Super resolution initialized: " + std::to_string(full_width_) + "x" + std::to_string(full_height_) + " scaling_px=" + std::to_string(config_.scaling) + " lowres=" + std::to_string(low_res_w_) + "x" + std::to_string(low_res_h_));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperResolution::release() {
|
void SuperResolution::release() {
|
||||||
if (!initialized_)
|
if (!initialized_) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ResourceManager &rm = ResourceManager::instance();
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
|
|
||||||
if (low_res_rt_texture_ != INVALID_HANDLE) {
|
if (low_res_rt_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(low_res_rt_texture_);
|
rm.destroy_texture(low_res_rt_texture_);
|
||||||
low_res_rt_texture_ = INVALID_HANDLE;
|
low_res_rt_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accumulated_rt_texture_ != INVALID_HANDLE) {
|
if (accumulated_rt_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(accumulated_rt_texture_);
|
rm.destroy_texture(accumulated_rt_texture_);
|
||||||
accumulated_rt_texture_ = INVALID_HANDLE;
|
accumulated_rt_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upscaled_texture_ != INVALID_HANDLE) {
|
if (upscaled_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(upscaled_texture_);
|
rm.destroy_texture(upscaled_texture_);
|
||||||
upscaled_texture_ = INVALID_HANDLE;
|
upscaled_texture_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
ARE_LOG_INFO("SuperResolution released");
|
ARE_LOG_INFO("SuperResolution released");
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle SuperResolution::upscale() {
|
TextureHandle SuperResolution::upscale() {
|
||||||
if (!initialized_ || !compute_shader_)
|
if (!initialized_ || !compute_shader_) {
|
||||||
return INVALID_HANDLE;
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
compute_shader_->use();
|
compute_shader_->use();
|
||||||
glBindImageTexture(1, accumulated_rt_texture_, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
glBindImageTexture(1, accumulated_rt_texture_, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||||
|
|
@ -84,26 +93,31 @@ void SuperResolution::reset_accumulation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperResolution::resize(uint full_width, uint full_height) {
|
void SuperResolution::resize(uint full_width, uint full_height) {
|
||||||
if (full_width == full_width_ && full_height == full_height_)
|
if (full_width == full_width_ && full_height == full_height_) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
full_width_ = full_width;
|
full_width_ = full_width;
|
||||||
full_height_ = full_height;
|
full_height_ = full_height;
|
||||||
uint block = compute_block_size_();
|
uint block = compute_block_size_();
|
||||||
low_res_w_ = full_width_ / block;
|
low_res_w_ = full_width_ / block;
|
||||||
low_res_h_ = full_height_ / block;
|
low_res_h_ = full_height_ / block;
|
||||||
if (!initialized_)
|
if (!initialized_) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ResourceManager &rm = ResourceManager::instance();
|
ResourceManager &rm = ResourceManager::instance();
|
||||||
if (low_res_rt_texture_ != INVALID_HANDLE) {
|
if (low_res_rt_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(low_res_rt_texture_);
|
rm.destroy_texture(low_res_rt_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accumulated_rt_texture_ != INVALID_HANDLE) {
|
if (accumulated_rt_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(accumulated_rt_texture_);
|
rm.destroy_texture(accumulated_rt_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upscaled_texture_ != INVALID_HANDLE) {
|
if (upscaled_texture_ != INVALID_HANDLE) {
|
||||||
rm.destroy_texture(upscaled_texture_);
|
rm.destroy_texture(upscaled_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
create_textures_();
|
create_textures_();
|
||||||
ARE_LOG_INFO("SuperResolution resized to " + std::to_string(full_width) + "x" + std::to_string(full_height));
|
ARE_LOG_INFO("SuperResolution resized to " + std::to_string(full_width) + "x" + std::to_string(full_height));
|
||||||
}
|
}
|
||||||
|
|
@ -122,8 +136,7 @@ void SuperResolution::clear_accumulation_texture_() const {
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, accumulated_rt_texture_, 0);
|
||||||
accumulated_rt_texture_, 0);
|
|
||||||
const GLfloat clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
const GLfloat clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
glClearBufferfv(GL_COLOR, 0, clear_color);
|
glClearBufferfv(GL_COLOR, 0, clear_color);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue