You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-18 14:21:41 +00:00
Implemented AMD's FSR as a computer shader for upscaling 3D scenes
This commit is contained in:
@@ -237,6 +237,43 @@ RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_te
|
||||
return uniform_set;
|
||||
}
|
||||
|
||||
void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
|
||||
memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
int dispatch_x = (p_size.x + 15) / 16;
|
||||
int dispatch_y = (p_size.y + 15) / 16;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
|
||||
|
||||
FSR_upscale.push_constant.resolution_width = p_internal_size.width;
|
||||
FSR_upscale.push_constant.resolution_height = p_internal_size.height;
|
||||
FSR_upscale.push_constant.upscaled_width = p_size.width;
|
||||
FSR_upscale.push_constant.upscaled_height = p_size.height;
|
||||
FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
|
||||
|
||||
//FSR Easc
|
||||
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
//FSR Rcas
|
||||
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end(compute_list);
|
||||
}
|
||||
|
||||
void EffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y, bool p_panorama) {
|
||||
memset(©_to_fb.push_constant, 0, sizeof(CopyToFbPushConstant));
|
||||
|
||||
@@ -1888,6 +1925,27 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
|
||||
}
|
||||
|
||||
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
{
|
||||
Vector<String> FSR_upscale_modes;
|
||||
|
||||
#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
|
||||
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
#else
|
||||
// Everyone else can use normal mode when available.
|
||||
if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
|
||||
} else {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
FSR_upscale.shader.initialize(FSR_upscale_modes);
|
||||
|
||||
FSR_upscale.shader_version = FSR_upscale.shader.version_create();
|
||||
FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
|
||||
}
|
||||
|
||||
prefer_raster_effects = p_prefer_raster_effects;
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
@@ -2523,6 +2581,7 @@ EffectsRD::~EffectsRD() {
|
||||
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
|
||||
RD::get_singleton()->free(filter.coefficient_buffer);
|
||||
|
||||
FSR_upscale.shader.version_free(FSR_upscale.shader_version);
|
||||
if (prefer_raster_effects) {
|
||||
blur_raster.shader.version_free(blur_raster.shader_version);
|
||||
bokeh.raster_shader.version_free(blur_raster.shader_version);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
|
||||
@@ -69,6 +70,28 @@ class EffectsRD {
|
||||
private:
|
||||
bool prefer_raster_effects;
|
||||
|
||||
enum FSRUpscalePass {
|
||||
FSR_UPSCALE_PASS_EASU = 0,
|
||||
FSR_UPSCALE_PASS_RCAS = 1
|
||||
};
|
||||
|
||||
struct FSRUpscalePushConstant {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float upscaled_width;
|
||||
float upscaled_height;
|
||||
float sharpness;
|
||||
int pass;
|
||||
int _unused0, _unused1;
|
||||
};
|
||||
|
||||
struct FSRUpscale {
|
||||
FSRUpscalePushConstant push_constant;
|
||||
FsrUpscaleShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
} FSR_upscale;
|
||||
|
||||
enum BlurRasterMode {
|
||||
BLUR_MIPMAP,
|
||||
|
||||
@@ -754,6 +777,7 @@ private:
|
||||
public:
|
||||
bool get_prefer_raster_effects();
|
||||
|
||||
void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
|
||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
|
||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
|
||||
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
|
||||
|
||||
@@ -1954,7 +1954,9 @@ void RenderForwardClustered::_base_uniforms_changed() {
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_update_render_base_uniform_set() {
|
||||
if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
|
||||
if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
|
||||
base_uniform_set_updated = false;
|
||||
|
||||
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
|
||||
RD::get_singleton()->free(render_base_uniform_set);
|
||||
}
|
||||
@@ -1969,18 +1971,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
|
||||
u.binding = 1;
|
||||
u.ids.resize(12);
|
||||
RID *ids_ptr = u.ids.ptrw();
|
||||
ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@@ -1999,19 +2001,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
|
||||
RID sampler;
|
||||
switch (decals_get_filter()) {
|
||||
case RS::DECAL_FILTER_NEAREST: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::DECAL_FILTER_LINEAR: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
}
|
||||
|
||||
@@ -2026,19 +2028,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
|
||||
RID sampler;
|
||||
switch (light_projectors_get_filter()) {
|
||||
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
|
||||
sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
virtual void _base_uniforms_changed() override;
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
|
||||
|
||||
bool base_uniform_set_updated = false;
|
||||
void _update_render_base_uniform_set();
|
||||
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
|
||||
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
|
||||
@@ -603,6 +604,11 @@ protected:
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ virtual void update_uniform_sets() override {
|
||||
base_uniform_set_updated = true;
|
||||
_update_render_base_uniform_set();
|
||||
}
|
||||
|
||||
virtual GeometryInstance *geometry_instance_create(RID p_base) override;
|
||||
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
|
||||
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
|
||||
|
||||
@@ -281,12 +281,12 @@ RendererCompositorRD::RendererCompositorRD() {
|
||||
storage = memnew(RendererStorageRD);
|
||||
canvas = memnew(RendererCanvasRenderRD(storage));
|
||||
|
||||
uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end");
|
||||
back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
|
||||
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
|
||||
|
||||
if (back_end == 1 || textures_per_stage < 48) {
|
||||
if (back_end || textures_per_stage < 48) {
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
|
||||
} else { // back_end == 0
|
||||
} else { // back_end == false
|
||||
// default to our high end renderer
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
|
||||
}
|
||||
|
||||
@@ -116,8 +116,6 @@ public:
|
||||
_create_func = _create_current;
|
||||
}
|
||||
|
||||
virtual bool is_low_end() const { return false; }
|
||||
|
||||
static RendererCompositorRD *singleton;
|
||||
RendererCompositorRD();
|
||||
~RendererCompositorRD();
|
||||
|
||||
@@ -3132,8 +3132,8 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
if (half_resolution) {
|
||||
tf.width >>= 1;
|
||||
tf.height >>= 1;
|
||||
@@ -3146,13 +3146,13 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
|
||||
|
||||
PushConstant push_constant;
|
||||
|
||||
push_constant.screen_size[0] = rb->width;
|
||||
push_constant.screen_size[1] = rb->height;
|
||||
push_constant.screen_size[0] = rb->internal_width;
|
||||
push_constant.screen_size[1] = rb->internal_height;
|
||||
push_constant.z_near = p_projection.get_z_near();
|
||||
push_constant.z_far = p_projection.get_z_far();
|
||||
push_constant.orthogonal = p_projection.is_orthogonal();
|
||||
push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]);
|
||||
push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]);
|
||||
push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]);
|
||||
push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]);
|
||||
push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
|
||||
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
|
||||
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
|
||||
@@ -3344,9 +3344,9 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
if (rb->gi.using_half_size_gi) {
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
|
||||
}
|
||||
//do barrier later to allow oeverlap
|
||||
//RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
|
||||
|
||||
@@ -1503,8 +1503,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
|
||||
tf.array_layers = rb->view_count;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
@@ -1515,6 +1515,10 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
||||
}
|
||||
tf.mipmaps = mipmaps_required;
|
||||
|
||||
rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
//the second one is smaller (only used for separatable part of blur)
|
||||
tf.width >>= 1;
|
||||
@@ -1522,8 +1526,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
||||
tf.mipmaps--;
|
||||
rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
int base_width = rb->width;
|
||||
int base_height = rb->height;
|
||||
int base_width = rb->internal_width;
|
||||
int base_height = rb->internal_height;
|
||||
|
||||
for (uint32_t i = 0; i < mipmaps_required; i++) {
|
||||
RenderBuffers::Blur::Mipmap mm;
|
||||
@@ -1577,8 +1581,8 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
||||
// create 4 weight textures, 2 full size, 2 half size
|
||||
|
||||
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
|
||||
tf.array_layers = rb->view_count;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
@@ -1656,8 +1660,8 @@ void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *r
|
||||
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
|
||||
ERR_FAIL_COND(!rb->luminance.current.is_null());
|
||||
|
||||
int w = rb->width;
|
||||
int h = rb->height;
|
||||
int w = rb->internal_width;
|
||||
int h = rb->internal_height;
|
||||
|
||||
while (true) {
|
||||
w = MAX(w / 8, 1);
|
||||
@@ -1709,9 +1713,26 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
|
||||
rb->texture_fb = RID();
|
||||
}
|
||||
|
||||
if (rb->texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->texture);
|
||||
if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->internal_texture);
|
||||
rb->texture = RID();
|
||||
rb->internal_texture = RID();
|
||||
rb->upscale_texture = RID();
|
||||
} else {
|
||||
if (rb->texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->texture);
|
||||
rb->texture = RID();
|
||||
}
|
||||
|
||||
if (rb->internal_texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->internal_texture);
|
||||
rb->internal_texture = RID();
|
||||
}
|
||||
|
||||
if (rb->upscale_texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->upscale_texture);
|
||||
rb->upscale_texture = RID();
|
||||
}
|
||||
}
|
||||
|
||||
if (rb->depth_texture.is_valid()) {
|
||||
@@ -1729,6 +1750,11 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
|
||||
rb->depth_back_texture = RID();
|
||||
}
|
||||
|
||||
if (rb->sss_texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->sss_texture);
|
||||
rb->sss_texture = RID();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
|
||||
// do we free the texture slice here? or is it enough to free the main texture?
|
||||
@@ -1818,7 +1844,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
|
||||
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
|
||||
bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
|
||||
|
||||
if (!can_use_effects) {
|
||||
//just copy
|
||||
@@ -1829,18 +1855,18 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
|
||||
_allocate_blur_textures(rb);
|
||||
}
|
||||
|
||||
storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
|
||||
storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
|
||||
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
|
||||
bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
|
||||
|
||||
if (!can_use_effects) {
|
||||
//just copy
|
||||
storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, RID());
|
||||
storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1852,8 +1878,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
|
||||
if (rb->ssr.depth_scaled.is_null()) {
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
|
||||
tf.width = rb->width / 2;
|
||||
tf.height = rb->height / 2;
|
||||
tf.width = rb->internal_width / 2;
|
||||
tf.height = rb->internal_height / 2;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
@@ -1867,8 +1893,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
|
||||
if (ssr_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R8_UNORM;
|
||||
tf.width = rb->width / 2;
|
||||
tf.height = rb->height / 2;
|
||||
tf.width = rb->internal_width / 2;
|
||||
tf.height = rb->internal_height / 2;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
@@ -1880,8 +1906,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
|
||||
_allocate_blur_textures(rb);
|
||||
}
|
||||
|
||||
storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
|
||||
storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture);
|
||||
storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
|
||||
storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].mipmaps[1].texture);
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
|
||||
@@ -1918,15 +1944,15 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
|
||||
int half_width;
|
||||
int half_height;
|
||||
if (ssao_half_size) {
|
||||
buffer_width = (rb->width + 3) / 4;
|
||||
buffer_height = (rb->height + 3) / 4;
|
||||
half_width = (rb->width + 7) / 8;
|
||||
half_height = (rb->height + 7) / 8;
|
||||
buffer_width = (rb->internal_width + 3) / 4;
|
||||
buffer_height = (rb->internal_height + 3) / 4;
|
||||
half_width = (rb->internal_width + 7) / 8;
|
||||
half_height = (rb->internal_height + 7) / 8;
|
||||
} else {
|
||||
buffer_width = (rb->width + 1) / 2;
|
||||
buffer_height = (rb->height + 1) / 2;
|
||||
half_width = (rb->width + 3) / 4;
|
||||
half_height = (rb->height + 3) / 4;
|
||||
buffer_width = (rb->internal_width + 1) / 2;
|
||||
buffer_height = (rb->internal_height + 1) / 2;
|
||||
half_width = (rb->internal_width + 3) / 4;
|
||||
half_height = (rb->internal_height + 3) / 4;
|
||||
}
|
||||
bool uniform_sets_are_invalid = false;
|
||||
if (rb->ssao.depth.is_null()) {
|
||||
@@ -1998,8 +2024,8 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
|
||||
{
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R8_UNORM;
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
|
||||
@@ -2022,7 +2048,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
|
||||
settings.blur_passes = ssao_blur_passes;
|
||||
settings.fadeout_from = ssao_fadeout_from;
|
||||
settings.fadeout_to = ssao_fadeout_to;
|
||||
settings.full_screen_size = Size2i(rb->width, rb->height);
|
||||
settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
|
||||
settings.half_screen_size = Size2i(buffer_width, buffer_height);
|
||||
settings.quarter_screen_size = Size2i(half_width, half_height);
|
||||
|
||||
@@ -2102,9 +2128,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
|
||||
EffectsRD::BokehBuffers buffers;
|
||||
|
||||
// Textures we use.
|
||||
buffers.base_texture_size = Size2i(rb->width, rb->height);
|
||||
buffers.base_texture = rb->texture;
|
||||
// Textures we use
|
||||
buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
|
||||
buffers.base_texture = rb->internal_texture;
|
||||
buffers.depth_texture = rb->depth_texture;
|
||||
buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
|
||||
buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
|
||||
@@ -2143,9 +2169,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
|
||||
double step = env->auto_exp_speed * time_step;
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
} else {
|
||||
storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
}
|
||||
// Swap final reduce with prev luminance.
|
||||
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
|
||||
@@ -2188,9 +2214,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
luminance_texture = rb->luminance.current;
|
||||
}
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
storage->get_effects()->gaussian_glow(rb->internal_texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
} else {
|
||||
storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
storage->get_effects()->gaussian_glow_raster(rb->internal_texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
}
|
||||
} else {
|
||||
if (can_use_storage) {
|
||||
@@ -2237,7 +2263,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
}
|
||||
|
||||
tonemap.use_debanding = rb->use_debanding;
|
||||
tonemap.texture_size = Vector2i(rb->width, rb->height);
|
||||
tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
|
||||
|
||||
if (env) {
|
||||
tonemap.tonemap_mode = env->tone_mapper;
|
||||
@@ -2268,7 +2294,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||
tonemap.view_count = p_render_data->view_count;
|
||||
|
||||
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
|
||||
storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
|
||||
RD::get_singleton()->draw_command_begin_label("FSR Upscale");
|
||||
|
||||
storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
@@ -2628,14 +2662,28 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
p_internal_height = p_height;
|
||||
p_internal_width = p_width;
|
||||
}
|
||||
|
||||
if (p_width != p_internal_width) {
|
||||
float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
|
||||
storage->sampler_rd_configure_custom(fsr_mipmap_bias);
|
||||
update_uniform_sets();
|
||||
}
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
|
||||
|
||||
// Should we add an overrule per viewport?
|
||||
rb->internal_width = p_internal_width;
|
||||
rb->internal_height = p_internal_height;
|
||||
rb->width = p_width;
|
||||
rb->height = p_height;
|
||||
rb->fsr_sharpness = p_fsr_sharpness;
|
||||
rb->render_target = p_render_target;
|
||||
rb->msaa = p_msaa;
|
||||
rb->screen_space_aa = p_screen_space_aa;
|
||||
@@ -2657,8 +2705,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
tf.format = _render_buffers_get_color_format();
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width; // If set to rb->width, msaa won't crash
|
||||
tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
|
||||
tf.array_layers = rb->view_count; // create a layer for every view
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
@@ -2666,7 +2714,17 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
||||
}
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
|
||||
|
||||
rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
if ((p_internal_width != p_width || p_internal_height != p_height)) {
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
} else {
|
||||
rb->texture = rb->internal_texture;
|
||||
rb->upscale_texture = rb->internal_texture;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -2680,8 +2738,8 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
||||
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
|
||||
}
|
||||
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
tf.array_layers = rb->view_count; // create a layer for every view
|
||||
|
||||
@@ -2697,16 +2755,16 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
// ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
|
||||
Vector<RID> fb;
|
||||
fb.push_back(rb->texture);
|
||||
fb.push_back(rb->internal_texture);
|
||||
|
||||
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
|
||||
}
|
||||
|
||||
RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
|
||||
rb->data->configure(rb->texture, rb->depth_texture, target_texture, rb->width, rb->height, p_msaa, p_view_count);
|
||||
rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
|
||||
|
||||
if (is_clustered_enabled()) {
|
||||
rb->cluster_builder->setup(Size2i(rb->width, rb->height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
|
||||
rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4704,9 +4762,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
|
||||
if (p_render_buffers.is_valid()) {
|
||||
/*
|
||||
_debug_draw_cluster(p_render_buffers);
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
||||
_render_buffers_post_process_and_tonemap(&render_data);
|
||||
*/
|
||||
|
||||
|
||||
@@ -456,7 +456,11 @@ private:
|
||||
|
||||
struct RenderBuffers {
|
||||
RenderBufferData *data = nullptr;
|
||||
int width = 0, height = 0;
|
||||
int internal_width = 0;
|
||||
int internal_height = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
float fsr_sharpness = 0.2f;
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
bool use_debanding = false;
|
||||
@@ -466,9 +470,12 @@ private:
|
||||
|
||||
uint64_t auto_exposure_version = 1;
|
||||
|
||||
RID texture; //main texture for rendering to, must be filled after done rendering
|
||||
RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
|
||||
RID internal_texture; //main texture for rendering to, must be filled after done rendering
|
||||
RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
|
||||
RID depth_texture; //main depth texture
|
||||
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
||||
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
|
||||
|
||||
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
|
||||
VolumetricFog *volumetric_fog = nullptr;
|
||||
@@ -1332,7 +1339,7 @@ public:
|
||||
virtual RD::DataFormat _render_buffers_get_color_format();
|
||||
virtual bool _render_buffers_can_be_storage();
|
||||
virtual RID render_buffers_create() override;
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
virtual void gi_set_use_half_resolution(bool p_enable) override;
|
||||
|
||||
RID render_buffers_get_depth_texture(RID p_render_buffers);
|
||||
@@ -1363,6 +1370,8 @@ public:
|
||||
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
|
||||
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
|
||||
|
||||
virtual void update_uniform_sets(){};
|
||||
|
||||
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
|
||||
|
||||
virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
|
||||
@@ -1227,6 +1227,100 @@ RendererStorageRD::CanvasTexture::~CanvasTexture() {
|
||||
clear_sets();
|
||||
}
|
||||
|
||||
void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
|
||||
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
|
||||
for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
|
||||
RD::SamplerState sampler_state;
|
||||
switch (i) {
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
sampler_state.max_lod = 0;
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler_state.max_lod = 0;
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
} else {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
}
|
||||
sampler_state.lod_bias = p_mipmap_bias;
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
} else {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
}
|
||||
sampler_state.lod_bias = p_mipmap_bias;
|
||||
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
} else {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
}
|
||||
sampler_state.lod_bias = p_mipmap_bias;
|
||||
sampler_state.use_anisotropy = true;
|
||||
sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
|
||||
sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
|
||||
} else {
|
||||
sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
}
|
||||
sampler_state.lod_bias = p_mipmap_bias;
|
||||
sampler_state.use_anisotropy = true;
|
||||
sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
|
||||
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
switch (j) {
|
||||
case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
|
||||
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
|
||||
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
|
||||
sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
|
||||
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
|
||||
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
|
||||
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
|
||||
sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
|
||||
} break;
|
||||
case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
|
||||
sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
|
||||
sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
|
||||
sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
if (custom_rd_samplers[i][j].is_valid()) {
|
||||
RD::get_singleton()->free(custom_rd_samplers[i][j]);
|
||||
}
|
||||
|
||||
custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RID RendererStorageRD::canvas_texture_allocate() {
|
||||
return canvas_texture_owner.allocate_rid();
|
||||
}
|
||||
@@ -9774,6 +9868,9 @@ RendererStorageRD::RendererStorageRD() {
|
||||
}
|
||||
}
|
||||
|
||||
//custom sampler
|
||||
sampler_rd_configure_custom(0.0f);
|
||||
|
||||
//default rd buffers
|
||||
{
|
||||
Vector<uint8_t> buffer;
|
||||
@@ -10104,6 +10201,15 @@ RendererStorageRD::~RendererStorageRD() {
|
||||
}
|
||||
}
|
||||
|
||||
//custom samplers
|
||||
for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
|
||||
for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
|
||||
if (custom_rd_samplers[i][j].is_valid()) {
|
||||
RD::get_singleton()->free(custom_rd_samplers[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//def buffers
|
||||
for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
|
||||
RD::get_singleton()->free(mesh_default_rd_buffers[i]);
|
||||
|
||||
@@ -320,6 +320,7 @@ private:
|
||||
|
||||
RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
|
||||
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
|
||||
RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
|
||||
RID default_rd_storage_buffer;
|
||||
|
||||
/* DECAL ATLAS */
|
||||
@@ -1391,6 +1392,13 @@ public:
|
||||
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
|
||||
return default_rd_samplers[p_filter][p_repeat];
|
||||
}
|
||||
_FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
|
||||
return custom_rd_samplers[p_filter][p_repeat];
|
||||
}
|
||||
|
||||
void sampler_rd_configure_custom(float mipmap_bias);
|
||||
|
||||
void sampler_rd_set_default(float p_mipmap_bias);
|
||||
|
||||
/* CANVAS TEXTURE API */
|
||||
|
||||
|
||||
173
servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
Normal file
173
servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
Normal file
@@ -0,0 +1,173 @@
|
||||
/*************************************************************************/
|
||||
/* fsr_upscale.glsl */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of 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. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#define A_GPU
|
||||
#define A_GLSL
|
||||
|
||||
#ifdef MODE_FSR_UPSCALE_NORMAL
|
||||
|
||||
#define A_HALF
|
||||
|
||||
#endif
|
||||
|
||||
#include "thirdparty/amd-fsr/ffx_a.h"
|
||||
|
||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D fsr_image;
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_image;
|
||||
|
||||
#define FSR_UPSCALE_PASS_TYPE_EASU 0
|
||||
#define FSR_UPSCALE_PASS_TYPE_RCAS 1
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float upscaled_width;
|
||||
float upscaled_height;
|
||||
float sharpness;
|
||||
int pass;
|
||||
}
|
||||
params;
|
||||
|
||||
AU4 Const0, Const1, Const2, Const3;
|
||||
|
||||
#ifdef MODE_FSR_UPSCALE_FALLBACK
|
||||
|
||||
#define FSR_EASU_F
|
||||
AF4 FsrEasuRF(AF2 p) {
|
||||
AF4 res = textureGather(source_image, p, 0);
|
||||
return res;
|
||||
}
|
||||
AF4 FsrEasuGF(AF2 p) {
|
||||
AF4 res = textureGather(source_image, p, 1);
|
||||
return res;
|
||||
}
|
||||
AF4 FsrEasuBF(AF2 p) {
|
||||
AF4 res = textureGather(source_image, p, 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
#define FSR_RCAS_F
|
||||
AF4 FsrRcasLoadF(ASU2 p) {
|
||||
return AF4(texelFetch(source_image, ASU2(p), 0));
|
||||
}
|
||||
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
#else
|
||||
|
||||
#define FSR_EASU_H
|
||||
AH4 FsrEasuRH(AF2 p) {
|
||||
AH4 res = AH4(textureGather(source_image, p, 0));
|
||||
return res;
|
||||
}
|
||||
AH4 FsrEasuGH(AF2 p) {
|
||||
AH4 res = AH4(textureGather(source_image, p, 1));
|
||||
return res;
|
||||
}
|
||||
AH4 FsrEasuBH(AF2 p) {
|
||||
AH4 res = AH4(textureGather(source_image, p, 2));
|
||||
return res;
|
||||
}
|
||||
|
||||
#define FSR_RCAS_H
|
||||
AH4 FsrRcasLoadH(ASW2 p) {
|
||||
return AH4(texelFetch(source_image, ASU2(p), 0));
|
||||
}
|
||||
void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b) {}
|
||||
|
||||
#endif
|
||||
|
||||
#include "thirdparty/amd-fsr/ffx_fsr1.h"
|
||||
|
||||
void fsr_easu_pass(AU2 pos) {
|
||||
#ifdef MODE_FSR_UPSCALE_NORMAL
|
||||
|
||||
AH3 Gamma2Color = AH3(0, 0, 0);
|
||||
FsrEasuH(Gamma2Color, pos, Const0, Const1, Const2, Const3);
|
||||
imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
|
||||
|
||||
#else
|
||||
|
||||
AF3 Gamma2Color = AF3(0, 0, 0);
|
||||
FsrEasuF(Gamma2Color, pos, Const0, Const1, Const2, Const3);
|
||||
imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void fsr_rcas_pass(AU2 pos) {
|
||||
#ifdef MODE_FSR_UPSCALE_NORMAL
|
||||
|
||||
AH3 Gamma2Color = AH3(0, 0, 0);
|
||||
FsrRcasH(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
|
||||
imageStore(fsr_image, ASU2(pos), AH4(Gamma2Color, 1));
|
||||
|
||||
#else
|
||||
|
||||
AF3 Gamma2Color = AF3(0, 0, 0);
|
||||
FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, pos, Const0);
|
||||
imageStore(fsr_image, ASU2(pos), AF4(Gamma2Color, 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void fsr_pass(AU2 pos) {
|
||||
if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
|
||||
fsr_easu_pass(pos);
|
||||
} else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
|
||||
fsr_rcas_pass(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Clang does not like unused functions. If ffx_a.h is included in the binary, clang will throw a fit and not compile so we must configure FSR in this shader
|
||||
if (params.pass == FSR_UPSCALE_PASS_TYPE_EASU) {
|
||||
FsrEasuCon(Const0, Const1, Const2, Const3, params.resolution_width, params.resolution_height, params.resolution_width, params.resolution_height, params.upscaled_width, params.upscaled_height);
|
||||
} else if (params.pass == FSR_UPSCALE_PASS_TYPE_RCAS) {
|
||||
FsrRcasCon(Const0, params.sharpness);
|
||||
}
|
||||
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x) + AU2(gl_WorkGroupID.x << 4u, gl_WorkGroupID.y << 4u);
|
||||
|
||||
fsr_pass(gxy);
|
||||
gxy.x += 8u;
|
||||
fsr_pass(gxy);
|
||||
gxy.y += 8u;
|
||||
fsr_pass(gxy);
|
||||
gxy.x -= 8u;
|
||||
fsr_pass(gxy);
|
||||
}
|
||||
Reference in New Issue
Block a user