Add error checks for texture type and storage format mismatches.
This commit is contained in:
@@ -3667,7 +3667,7 @@ void GI::init(SkyRD *p_sky) {
|
||||
String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
|
||||
defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n";
|
||||
if (p_sky->sky_use_octmap_array) {
|
||||
defines += "\n#define USE_OCTMAP_ARRAY\n";
|
||||
defines += "\n#define USE_RADIANCE_OCTMAP_ARRAY\n";
|
||||
}
|
||||
|
||||
Vector<String> integrate_modes;
|
||||
|
||||
@@ -505,11 +505,21 @@ void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SkyRD::Sky
|
||||
|
||||
void SkyRD::Sky::free() {
|
||||
void SkyRD::Sky::free_radiance() {
|
||||
if (radiance.is_valid()) {
|
||||
RD::get_singleton()->free_rid(radiance);
|
||||
radiance = RID();
|
||||
}
|
||||
if (radiance_first_layer_slice.is_valid()) {
|
||||
if (RD::get_singleton()->texture_is_valid(radiance_first_layer_slice)) {
|
||||
RD::get_singleton()->free_rid(radiance_first_layer_slice);
|
||||
}
|
||||
radiance_first_layer_slice = RID();
|
||||
}
|
||||
}
|
||||
|
||||
void SkyRD::Sky::free() {
|
||||
free_radiance();
|
||||
reflection.clear_reflection_data();
|
||||
|
||||
if (uniform_buffer.is_valid()) {
|
||||
@@ -533,7 +543,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 0;
|
||||
if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
|
||||
u.append_id(radiance);
|
||||
u.append_id(radiance_first_layer_slice.is_valid() ? radiance_first_layer_slice : radiance);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
|
||||
}
|
||||
@@ -595,10 +605,7 @@ bool SkyRD::Sky::set_radiance_size(int p_radiance_size) {
|
||||
radiance_size = REAL_TIME_SIZE;
|
||||
}
|
||||
|
||||
if (radiance.is_valid()) {
|
||||
RD::get_singleton()->free_rid(radiance);
|
||||
radiance = RID();
|
||||
}
|
||||
free_radiance();
|
||||
reflection.clear_reflection_data();
|
||||
|
||||
return true;
|
||||
@@ -620,10 +627,7 @@ bool SkyRD::Sky::set_mode(RSE::SkyMode p_mode) {
|
||||
set_radiance_size(REAL_TIME_SIZE);
|
||||
}
|
||||
|
||||
if (radiance.is_valid()) {
|
||||
RD::get_singleton()->free_rid(radiance);
|
||||
radiance = RID();
|
||||
}
|
||||
free_radiance();
|
||||
reflection.clear_reflection_data();
|
||||
|
||||
return true;
|
||||
@@ -897,7 +901,7 @@ void sky() {
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 0;
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
@@ -1014,10 +1018,7 @@ void SkyRD::setup_sky(const RenderDataRD *p_render_data, const Size2i p_screen_s
|
||||
if (sky_mode != sky->internal_mode) {
|
||||
sky->internal_mode = sky_mode;
|
||||
|
||||
if (sky->radiance.is_valid()) {
|
||||
RD::get_singleton()->free_rid(sky->radiance);
|
||||
sky->radiance = RID();
|
||||
}
|
||||
sky->free_radiance();
|
||||
sky->reflection.clear_reflection_data();
|
||||
}
|
||||
} else {
|
||||
@@ -1571,6 +1572,9 @@ void SkyRD::update_dirty_skys() {
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
// Create view into the first layer slice for user shaders.
|
||||
sky->radiance_first_layer_slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sky->radiance, 0, 0, mipmaps, RD::TEXTURE_SLICE_2D, 1);
|
||||
|
||||
sky->reflection.update_reflection_data(w, mipmaps, true, sky->radiance, 0, use_realtime, roughness_layers, texture_format, sky->uv_border_size);
|
||||
} else {
|
||||
// Double size to approximate texel density of cubemaps + add border for proper filtering/mipmapping.
|
||||
@@ -1592,6 +1596,8 @@ void SkyRD::update_dirty_skys() {
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
DEV_ASSERT(sky->radiance_first_layer_slice.is_null());
|
||||
|
||||
sky->reflection.update_reflection_data(w, MIN(mipmaps, layers), false, sky->radiance, 0, use_realtime, roughness_layers, texture_format, sky->uv_border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +249,7 @@ public:
|
||||
static inline const int REAL_TIME_ROUGHNESS_LAYERS = 7;
|
||||
|
||||
RID radiance;
|
||||
RID radiance_first_layer_slice;
|
||||
RID quarter_res_pass;
|
||||
RID quarter_res_framebuffer;
|
||||
Size2i screen_size;
|
||||
@@ -275,6 +276,8 @@ public:
|
||||
Vector3 prev_position;
|
||||
float prev_time;
|
||||
|
||||
void free_radiance();
|
||||
|
||||
void free();
|
||||
|
||||
RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
|
||||
@@ -436,7 +436,7 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
|
||||
RID depth_back_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, v, 0);
|
||||
|
||||
if (can_use_storage) {
|
||||
copy_effects->copy_to_rect(depth_texture, depth_back_texture, Rect2i(0, 0, size.x, size.y));
|
||||
copy_effects->copy_depth_to_rect(depth_texture, depth_back_texture, Rect2i(0, 0, size.x, size.y));
|
||||
} else {
|
||||
RID depth_back_fb = FramebufferCacheRD::get_singleton()->get_cache(depth_back_texture);
|
||||
if (p_use_msaa) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source;
|
||||
layout(set = 0, binding = 1) uniform restrict writeonly image2D dest;
|
||||
layout(rgba16f, set = 0, binding = 1) uniform restrict writeonly image2D dest;
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
ivec2 screen_size;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
layout(rgba8, set = 0, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(r8, set = 0, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(set = 1, binding = 0) uniform sampler2DArray source_texture;
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
|
||||
@@ -71,7 +71,7 @@ layout(set = 0, binding = 2) uniform Constants { //get into a lower set
|
||||
constants;
|
||||
|
||||
#ifdef ADAPTIVE
|
||||
layout(rgba16, set = 1, binding = 0) uniform restrict readonly image2DArray source_ssil;
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict readonly image2DArray source_ssil;
|
||||
layout(set = 1, binding = 1) uniform sampler2D source_importance;
|
||||
layout(set = 1, binding = 2, std430) buffer Counter {
|
||||
uint sum;
|
||||
@@ -79,7 +79,7 @@ layout(set = 1, binding = 2, std430) buffer Counter {
|
||||
counter;
|
||||
#endif
|
||||
|
||||
layout(rgba16, set = 2, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(r8, set = 2, binding = 1) uniform image2D edges_weights_image;
|
||||
|
||||
layout(set = 3, binding = 0) uniform sampler2D last_frame;
|
||||
|
||||
@@ -28,7 +28,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_ssil;
|
||||
|
||||
layout(rgba16, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
|
||||
layout(r8, set = 2, binding = 0) uniform restrict readonly image2D source_edges;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
|
||||
layout(rgba16, set = 0, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
layout(set = 1, binding = 0) uniform sampler2DArray source_texture;
|
||||
layout(r8, set = 2, binding = 0) uniform restrict readonly image2DArray source_edges;
|
||||
|
||||
|
||||
@@ -4451,6 +4451,9 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
|
||||
Texture *texture = texture_owner.get_or_null(texture_id);
|
||||
ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(texture->type != set_uniform.texture_type, RID(),
|
||||
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs to have the same type as the uniform.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
|
||||
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
|
||||
|
||||
@@ -4501,6 +4504,9 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
|
||||
Texture *texture = texture_owner.get_or_null(texture_id);
|
||||
ERR_FAIL_NULL_V_MSG(texture, RID(), "Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(texture->type != set_uniform.texture_type, RID(),
|
||||
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs to have the same type as the uniform.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT), RID(),
|
||||
"Texture (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_SAMPLING_BIT usage flag set in order to be used as uniform.");
|
||||
|
||||
@@ -4552,6 +4558,13 @@ RID RenderingDevice::uniform_set_create(const VectorView<RD::Uniform> &p_uniform
|
||||
ERR_FAIL_NULL_V_MSG(texture, RID(),
|
||||
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") is not a valid texture.");
|
||||
|
||||
ERR_FAIL_COND_V_MSG(texture->type != set_uniform.texture_type, RID(),
|
||||
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs to have the same texture type as the uniform.");
|
||||
|
||||
if (likely(set_uniform.texture_format != RD::DATA_FORMAT_MAX) && unlikely(texture->format != set_uniform.texture_format)) {
|
||||
print_verbose("Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs to have the same texture format as the uniform (expected: " + String(FORMAT_NAMES[set_uniform.texture_format]) + ", actual: " + String(FORMAT_NAMES[texture->format]) + ").");
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), RID(),
|
||||
"Image (binding: " + itos(uniform.binding) + ", index " + itos(j) + ") needs the TEXTURE_USAGE_STORAGE_BIT usage flag set in order to be used as uniform.");
|
||||
|
||||
|
||||
@@ -1115,6 +1115,8 @@ public:
|
||||
uint32_t binding = 0;
|
||||
BitField<ShaderStage> stages = {};
|
||||
uint32_t length = 0; // Size of arrays (in total elements), or ubos (in bytes * total elements).
|
||||
TextureType texture_type = TEXTURE_TYPE_MAX;
|
||||
DataFormat texture_format = DATA_FORMAT_MAX;
|
||||
|
||||
bool operator!=(const ShaderUniform &p_other) const {
|
||||
return binding != p_other.binding || type != p_other.type || writable != p_other.writable || stages != p_other.stages || length != p_other.length;
|
||||
|
||||
@@ -139,7 +139,22 @@ void RenderingShaderContainer::_set_from_shader_reflection_post(const ReflectSha
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
static RenderingDeviceCommons::DataFormat spv_image_format_to_data_format(const SpvImageFormat p_format) {
|
||||
static RenderingDeviceCommons::TextureType _spv_image_dim_to_texture_type(SpvDim p_dim, bool p_arrayed) {
|
||||
switch (p_dim) {
|
||||
case SpvDim1D:
|
||||
return p_arrayed ? RenderingDeviceCommons::TEXTURE_TYPE_1D_ARRAY : RenderingDeviceCommons::TEXTURE_TYPE_1D;
|
||||
case SpvDim2D:
|
||||
return p_arrayed ? RenderingDeviceCommons::TEXTURE_TYPE_2D_ARRAY : RenderingDeviceCommons::TEXTURE_TYPE_2D;
|
||||
case SpvDim3D:
|
||||
return RenderingDeviceCommons::TEXTURE_TYPE_3D;
|
||||
case SpvDimCube:
|
||||
return p_arrayed ? RenderingDeviceCommons::TEXTURE_TYPE_CUBE_ARRAY : RenderingDeviceCommons::TEXTURE_TYPE_CUBE;
|
||||
default:
|
||||
return RenderingDeviceCommons::TEXTURE_TYPE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static RenderingDeviceCommons::DataFormat _spv_image_format_to_data_format(const SpvImageFormat p_format) {
|
||||
using RDC = RenderingDeviceCommons;
|
||||
switch (p_format) {
|
||||
case SpvImageFormatUnknown:
|
||||
@@ -439,7 +454,11 @@ Error RenderingShaderContainer::reflect_spirv(const String &p_shader_name, Span<
|
||||
}
|
||||
|
||||
if (is_image) {
|
||||
uniform.image.format = spv_image_format_to_data_format(binding.image.image_format);
|
||||
uniform.texture_type = _spv_image_dim_to_texture_type(binding.image.dim, binding.image.arrayed);
|
||||
uniform.texture_format = _spv_image_format_to_data_format(binding.image.image_format);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(uniform.texture_type == RDC::TEXTURE_TYPE_MAX, FAILED,
|
||||
"On shader stage '" + String(RDC::SHADER_STAGE_NAMES[stage]) + "', uniform '" + binding.name + "' does not have a valid texture type.");
|
||||
}
|
||||
|
||||
uniform.binding = binding.binding;
|
||||
@@ -681,6 +700,8 @@ void RenderingShaderContainer::set_from_shader_reflection(const ReflectShader &p
|
||||
binding_data.stages = uint32_t(uniform.stages);
|
||||
binding_data.length = uniform.length;
|
||||
binding_data.writable = uint32_t(uniform.writable);
|
||||
binding_data.texture_type = uniform.texture_type;
|
||||
binding_data.texture_format = uniform.texture_format;
|
||||
reflection_binding_set_uniforms_data.push_back(binding_data);
|
||||
}
|
||||
|
||||
@@ -743,6 +764,8 @@ RenderingDeviceCommons::ShaderReflection RenderingShaderContainer::get_shader_re
|
||||
uniform.length = binding.length;
|
||||
uniform.binding = binding.binding;
|
||||
uniform.stages = binding.stages;
|
||||
uniform.texture_type = binding.texture_type;
|
||||
uniform.texture_format = binding.texture_format;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ protected:
|
||||
uint32_t stages = 0;
|
||||
uint32_t length = 0; // Size of arrays (in total elements), or UBOs (in bytes * total elements).
|
||||
uint32_t writable = 0;
|
||||
RDC::TextureType texture_type = RDC::TEXTURE_TYPE_MAX;
|
||||
RDC::DataFormat texture_format = RDC::DATA_FORMAT_MAX;
|
||||
|
||||
bool operator<(const ReflectionBindingData &p_other) const {
|
||||
return binding < p_other.binding;
|
||||
@@ -162,18 +164,13 @@ protected:
|
||||
void set_spv_reflect(RDC::ShaderStage p_stage, const T *p_spv);
|
||||
};
|
||||
|
||||
struct ReflectImageTraits {
|
||||
RDC::DataFormat format = RDC::DATA_FORMAT_MAX;
|
||||
};
|
||||
|
||||
struct ReflectUniform : ReflectSymbol<SpvReflectDescriptorBinding> {
|
||||
RDC::UniformType type = RDC::UniformType::UNIFORM_TYPE_MAX;
|
||||
uint32_t binding = 0;
|
||||
|
||||
ReflectImageTraits image;
|
||||
|
||||
uint32_t length = 0; // Size of arrays (in total elements), or ubos (in bytes * total elements).
|
||||
bool writable = false;
|
||||
RDC::TextureType texture_type = RDC::TEXTURE_TYPE_MAX;
|
||||
RDC::DataFormat texture_format = RDC::DATA_FORMAT_MAX;
|
||||
|
||||
bool operator<(const ReflectUniform &p_other) const {
|
||||
if (binding != p_other.binding) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h b/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
index b610037cc6..346b3ec750 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
@@ -241,7 +241,7 @@ layout (set = 0, binding = 1) uniform sampler s_LinearClamp;
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_DILATED_MOTION_VECTORS, rg16f) writeonly uniform image2D rw_dilated_motion_vectors;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_DILATED_DEPTH
|
||||
- layout (set = 1, binding = FSR2_BIND_UAV_DILATED_DEPTH, r16f) writeonly uniform image2D rw_dilatedDepth;
|
||||
+ layout (set = 1, binding = FSR2_BIND_UAV_DILATED_DEPTH, r32f) writeonly uniform image2D rw_dilatedDepth;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_INTERNAL_UPSCALED
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_INTERNAL_UPSCALED, rgba16f) writeonly uniform image2D rw_internal_upscaled_color;
|
||||
@@ -256,7 +256,7 @@ layout (set = 0, binding = 1) uniform sampler s_LinearClamp;
|
||||
layout(set = 1, binding = FSR2_BIND_UAV_NEW_LOCKS, r8) uniform image2D rw_new_locks;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_PREPARED_INPUT_COLOR
|
||||
- layout (set = 1, binding = FSR2_BIND_UAV_PREPARED_INPUT_COLOR, rgba16) writeonly uniform image2D rw_prepared_input_color;
|
||||
+ layout (set = 1, binding = FSR2_BIND_UAV_PREPARED_INPUT_COLOR, rgba16f) writeonly uniform image2D rw_prepared_input_color;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_LUMA_HISTORY
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_LUMA_HISTORY, rgba8) uniform image2D rw_luma_history;
|
||||
+2
-2
@@ -241,7 +241,7 @@ layout (set = 0, binding = 1) uniform sampler s_LinearClamp;
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_DILATED_MOTION_VECTORS, rg16f) writeonly uniform image2D rw_dilated_motion_vectors;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_DILATED_DEPTH
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_DILATED_DEPTH, r16f) writeonly uniform image2D rw_dilatedDepth;
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_DILATED_DEPTH, r32f) writeonly uniform image2D rw_dilatedDepth;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_INTERNAL_UPSCALED
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_INTERNAL_UPSCALED, rgba16f) writeonly uniform image2D rw_internal_upscaled_color;
|
||||
@@ -256,7 +256,7 @@ layout (set = 0, binding = 1) uniform sampler s_LinearClamp;
|
||||
layout(set = 1, binding = FSR2_BIND_UAV_NEW_LOCKS, r8) uniform image2D rw_new_locks;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_PREPARED_INPUT_COLOR
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_PREPARED_INPUT_COLOR, rgba16) writeonly uniform image2D rw_prepared_input_color;
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_PREPARED_INPUT_COLOR, rgba16f) writeonly uniform image2D rw_prepared_input_color;
|
||||
#endif
|
||||
#if defined FSR2_BIND_UAV_LUMA_HISTORY
|
||||
layout (set = 1, binding = FSR2_BIND_UAV_LUMA_HISTORY, rgba8) uniform image2D rw_luma_history;
|
||||
|
||||
Reference in New Issue
Block a user