(shader_gl_core.cpp) Simplify

This commit is contained in:
twinaphex 2019-04-24 20:25:37 +02:00
parent c85bf21fbb
commit 3225876f0b

View File

@ -92,6 +92,8 @@ GLuint gl_core_cross_compile_program(
GLuint program = 0;
try
{
spirv_cross::ShaderResources vertex_resources;
spirv_cross::ShaderResources fragment_resources;
spirv_cross::CompilerGLSL vertex_compiler(vertex, vertex_size / 4);
spirv_cross::CompilerGLSL fragment_compiler(fragment, fragment_size / 4);
spirv_cross::CompilerGLSL::Options opts;
@ -105,11 +107,12 @@ GLuint gl_core_cross_compile_program(
opts.fragment.default_float_precision = spirv_cross::CompilerGLSL::Options::Precision::Highp;
opts.fragment.default_int_precision = spirv_cross::CompilerGLSL::Options::Precision::Highp;
opts.enable_420pack_extension = false;
vertex_compiler.set_common_options(opts);
fragment_compiler.set_common_options(opts);
auto vertex_resources = vertex_compiler.get_shader_resources();
auto fragment_resources = fragment_compiler.get_shader_resources();
vertex_resources = vertex_compiler.get_shader_resources();
fragment_resources = fragment_compiler.get_shader_resources();
for (auto &res : vertex_resources.stage_inputs)
{
@ -276,7 +279,7 @@ GLuint gl_core_cross_compile_program(
}
}
// Force proper bindings for textures.
/* Force proper bindings for textures. */
for (auto &binding : texture_binding_fixups)
{
GLint location = glGetUniformLocation(program, (string("RARCH_TEXTURE_") + to_string(binding)).c_str());
@ -320,7 +323,8 @@ static unsigned num_miplevels(unsigned width, unsigned height)
{
unsigned size = MAX(width, height);
unsigned levels = 0;
while (size) {
while (size)
{
levels++;
size >>= 1;
}
@ -372,44 +376,44 @@ static gl_core_filter_chain_address wrap_to_address(gfx_wrap_type type)
{
switch (type)
{
default:
case RARCH_WRAP_EDGE:
return GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE;
case RARCH_WRAP_BORDER:
return GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER;
case RARCH_WRAP_REPEAT:
return GL_CORE_FILTER_CHAIN_ADDRESS_REPEAT;
case RARCH_WRAP_MIRRORED_REPEAT:
return GL_CORE_FILTER_CHAIN_ADDRESS_MIRRORED_REPEAT;
case RARCH_WRAP_EDGE:
default:
break;
}
return GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE;
}
static GLenum address_to_gl(gl_core_filter_chain_address type)
{
switch (type)
{
default:
case GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE:
return GL_CLAMP_TO_EDGE;
#ifdef HAVE_OPENGLES3
case GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER:
//RARCH_WARN("[GLCore]: No CLAMP_TO_BORDER in GLES3. Falling back to edge clamp.\n");
#if 0
RARCH_WARN("[GLCore]: No CLAMP_TO_BORDER in GLES3. Falling back to edge clamp.\n");
#endif
return GL_CLAMP_TO_EDGE;
#else
case GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_BORDER:
return GL_CLAMP_TO_BORDER;
#endif
case GL_CORE_FILTER_CHAIN_ADDRESS_REPEAT:
return GL_REPEAT;
case GL_CORE_FILTER_CHAIN_ADDRESS_MIRRORED_REPEAT:
return GL_MIRRORED_REPEAT;
case GL_CORE_FILTER_CHAIN_ADDRESS_CLAMP_TO_EDGE:
default:
break;
}
return GL_CLAMP_TO_EDGE;
}
static GLenum convert_filter_to_mag_gl(gl_core_filter_chain_filter filter)
@ -418,11 +422,12 @@ static GLenum convert_filter_to_mag_gl(gl_core_filter_chain_filter filter)
{
case GL_CORE_FILTER_CHAIN_LINEAR:
return GL_LINEAR;
default:
case GL_CORE_FILTER_CHAIN_NEAREST:
return GL_NEAREST;
default:
break;
}
return GL_NEAREST;
}
static GLenum convert_filter_to_min_gl(gl_core_filter_chain_filter filter, gl_core_filter_chain_filter mipfilter)
@ -433,7 +438,6 @@ static GLenum convert_filter_to_min_gl(gl_core_filter_chain_filter filter, gl_co
return GL_LINEAR_MIPMAP_NEAREST;
else if (mipfilter == GL_CORE_FILTER_CHAIN_LINEAR)
return GL_NEAREST_MIPMAP_LINEAR;
else
return GL_NEAREST_MIPMAP_NEAREST;
}
@ -656,7 +660,7 @@ Framebuffer::Framebuffer(GLenum format_, unsigned max_levels_)
{
glGenFramebuffers(1, &framebuffer);
// Need to bind to create.
/* Need to bind to create */
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -729,12 +733,14 @@ void Framebuffer::init()
if (fallback)
{
unsigned levels;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glDeleteTextures(1, &image);
glGenTextures(1, &image);
glBindTexture(GL_TEXTURE_2D, image);
unsigned levels = num_miplevels(size.width, size.height);
levels = num_miplevels(size.width, size.height);
if (max_levels < levels)
levels = max_levels;
glTexStorage2D(GL_TEXTURE_2D, levels,
@ -865,41 +871,38 @@ class UBORing
public:
~UBORing();
void init(size_t size, unsigned count);
void update_and_bind(unsigned vertex_binding, unsigned fragment_binding, const void *data, size_t size);
private:
std::vector<GLuint> buffers;
unsigned buffer_index = 0;
};
void UBORing::init(size_t size, unsigned count)
{
unsigned i;
buffers.resize(count);
glGenBuffers(count, buffers.data());
for (auto &buf : buffers)
for (i = 0; i < buffers.size(); i++)
{
glBindBuffer(GL_UNIFORM_BUFFER, buf);
glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, buffers[i]);
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STREAM_DRAW);
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void UBORing::update_and_bind(unsigned vertex_binding, unsigned fragment_binding, const void *data, size_t size)
static void ubo_ring_update_and_bind(
unsigned vertex_binding,
unsigned fragment_binding,
const void *data, size_t size, GLuint id)
{
if (vertex_binding == GL_INVALID_INDEX && fragment_binding == GL_INVALID_INDEX)
return;
glBindBuffer(GL_UNIFORM_BUFFER, buffers[buffer_index]);
glBindBuffer(GL_UNIFORM_BUFFER, id);
glBufferSubData(GL_UNIFORM_BUFFER, 0, size, data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
if (vertex_binding != GL_INVALID_INDEX)
glBindBufferBase(GL_UNIFORM_BUFFER, vertex_binding, buffers[buffer_index]);
glBindBufferBase(GL_UNIFORM_BUFFER, vertex_binding, id);
if (fragment_binding != GL_INVALID_INDEX)
glBindBufferBase(GL_UNIFORM_BUFFER, fragment_binding, buffers[buffer_index]);
buffer_index++;
if (buffer_index >= buffers.size())
buffer_index = 0;
glBindBufferBase(GL_UNIFORM_BUFFER, fragment_binding, id);
}
UBORing::~UBORing()
@ -1024,7 +1027,8 @@ private:
void set_semantic_texture(slang_texture_semantic semantic,
const Texture &texture);
void set_semantic_texture_array(slang_texture_semantic semantic, unsigned index,
void set_semantic_texture_array(slang_texture_semantic semantic,
unsigned index,
const Texture &texture);
slang_reflection reflection;
@ -1032,10 +1036,12 @@ private:
std::vector<uint8_t> uniforms;
void build_semantics(uint8_t *buffer,
const float *mvp, const Texture &original, const Texture &source);
const float *mvp,
const Texture &original, const Texture &source);
void build_semantic_vec4(uint8_t *data, slang_semantic semantic,
unsigned width, unsigned height);
void build_semantic_uint(uint8_t *data, slang_semantic semantic, uint32_t value);
void build_semantic_uint(uint8_t *data,
slang_semantic semantic, uint32_t value);
void build_semantic_parameter(uint8_t *data, unsigned index, float value);
void build_semantic_texture_vec4(uint8_t *data,
slang_texture_semantic semantic,
@ -1046,7 +1052,8 @@ private:
void build_semantic_texture(uint8_t *buffer,
slang_texture_semantic semantic, const Texture &texture);
void build_semantic_texture_array(uint8_t *buffer,
slang_texture_semantic semantic, unsigned index, const Texture &texture);
slang_texture_semantic semantic,
unsigned index, const Texture &texture);
uint64_t frame_count = 0;
unsigned frame_count_period = 0;
@ -1083,10 +1090,8 @@ bool Pass::build()
framebuffer_feedback.reset();
if (!final_pass)
{
framebuffer = unique_ptr<Framebuffer>(
new Framebuffer(pass_info.rt_format, pass_info.max_levels));
}
for (auto &param : parameters)
{
@ -1173,38 +1178,44 @@ void Pass::reflect_parameter(const std::string &name, slang_texture_semantic_met
void Pass::reflect_parameter_array(const std::string &name, std::vector<slang_texture_semantic_meta> &meta)
{
for (size_t i = 0; i < meta.size(); i++)
size_t i;
for (i = 0; i < meta.size(); i++)
{
auto n = name + std::to_string(i);
auto &m = meta[i];
std::string n = name + std::to_string(i);
slang_texture_semantic_meta *m = (slang_texture_semantic_meta*)&meta[i];
if (m.uniform)
if (m->uniform)
{
int vert = glGetUniformLocation(pipeline, (std::string("RARCH_UBO_VERTEX_INSTANCE.") + n).c_str());
int frag = glGetUniformLocation(pipeline, (std::string("RARCH_UBO_FRAGMENT_INSTANCE.") + n).c_str());
int vert = glGetUniformLocation(pipeline,
(std::string("RARCH_UBO_VERTEX_INSTANCE.") + n).c_str());
int frag = glGetUniformLocation(pipeline,
(std::string("RARCH_UBO_FRAGMENT_INSTANCE.") + n).c_str());
if (vert >= 0)
m.location.ubo_vertex = vert;
m->location.ubo_vertex = vert;
if (frag >= 0)
m.location.ubo_fragment = frag;
m->location.ubo_fragment = frag;
}
if (m.push_constant)
if (m->push_constant)
{
int vert = glGetUniformLocation(pipeline, (std::string("RARCH_PUSH_VERTEX_INSTANCE.") + n).c_str());
int frag = glGetUniformLocation(pipeline, (std::string("RARCH_PUSH_FRAGMENT_INSTANCE.") + n).c_str());
int vert = glGetUniformLocation(pipeline,
(std::string("RARCH_PUSH_VERTEX_INSTANCE.") + n).c_str());
int frag = glGetUniformLocation(pipeline,
(std::string("RARCH_PUSH_FRAGMENT_INSTANCE.") + n).c_str());
if (vert >= 0)
m.location.push_vertex = vert;
m->location.push_vertex = vert;
if (frag >= 0)
m.location.push_fragment = frag;
m->location.push_fragment = frag;
}
}
}
bool Pass::init_pipeline()
{
pipeline = gl_core_cross_compile_program(vertex_shader.data(), vertex_shader.size() * sizeof(uint32_t),
pipeline = gl_core_cross_compile_program(
vertex_shader.data(), vertex_shader.size() * sizeof(uint32_t),
fragment_shader.data(), fragment_shader.size() * sizeof(uint32_t),
&locations, false);
@ -1305,78 +1316,78 @@ void Pass::end_frame()
void Pass::build_semantic_vec4(uint8_t *data, slang_semantic semantic,
unsigned width, unsigned height)
{
auto &refl = reflection.semantics[semantic];
slang_semantic_meta *refl = (slang_semantic_meta*)
&reflection.semantics[semantic];
if (data && refl.uniform)
if (data && refl->uniform)
{
if (refl.location.ubo_vertex >= 0 || refl.location.ubo_fragment >= 0)
if (refl->location.ubo_vertex >= 0 || refl->location.ubo_fragment >= 0)
{
float v4[4];
build_vec4(v4, width, height);
if (refl.location.ubo_vertex >= 0)
glUniform4fv(refl.location.ubo_vertex, 1, v4);
if (refl.location.ubo_fragment >= 0)
glUniform4fv(refl.location.ubo_fragment, 1, v4);
if (refl->location.ubo_vertex >= 0)
glUniform4fv(refl->location.ubo_vertex, 1, v4);
if (refl->location.ubo_fragment >= 0)
glUniform4fv(refl->location.ubo_fragment, 1, v4);
}
else
{
build_vec4(
reinterpret_cast<float *>(data + refl.ubo_offset),
reinterpret_cast<float *>(data + refl->ubo_offset),
width,
height);
}
}
if (refl.push_constant)
if (refl->push_constant)
{
if (refl.location.push_vertex >= 0 || refl.location.push_fragment >= 0)
if ( refl->location.push_vertex >= 0 ||
refl->location.push_fragment >= 0)
{
float v4[4];
build_vec4(v4, width, height);
if (refl.location.push_vertex >= 0)
glUniform4fv(refl.location.push_vertex, 1, v4);
if (refl.location.push_fragment >= 0)
glUniform4fv(refl.location.push_fragment, 1, v4);
if (refl->location.push_vertex >= 0)
glUniform4fv(refl->location.push_vertex, 1, v4);
if (refl->location.push_fragment >= 0)
glUniform4fv(refl->location.push_fragment, 1, v4);
}
else
{
build_vec4(
reinterpret_cast<float *>(push_constant_buffer.data() + refl.push_constant_offset),
reinterpret_cast<float *>
(push_constant_buffer.data() + refl->push_constant_offset),
width,
height);
}
}
}
void Pass::build_semantic_parameter(uint8_t *data, unsigned index, float value)
{
auto &refl = reflection.semantic_float_parameters[index];
slang_semantic_meta *refl = (slang_semantic_meta*)
&reflection.semantic_float_parameters[index];
/* We will have filtered out stale parameters. */
if (data && refl.uniform)
if (data && refl->uniform)
{
if (refl.location.ubo_vertex >= 0 || refl.location.ubo_fragment >= 0)
if (refl->location.ubo_vertex >= 0 || refl->location.ubo_fragment >= 0)
{
if (refl.location.ubo_vertex >= 0)
glUniform1f(refl.location.ubo_vertex, value);
if (refl.location.ubo_fragment >= 0)
glUniform1f(refl.location.ubo_fragment, value);
if (refl->location.ubo_vertex >= 0)
glUniform1f(refl->location.ubo_vertex, value);
if (refl->location.ubo_fragment >= 0)
glUniform1f(refl->location.ubo_fragment, value);
}
else
*reinterpret_cast<float *>(data + refl.ubo_offset) = value;
*reinterpret_cast<float *>(data + refl->ubo_offset) = value;
}
if (refl.push_constant)
if (refl->push_constant)
{
if (refl.location.push_vertex >= 0 || refl.location.push_fragment >= 0)
if (refl->location.push_vertex >= 0 || refl->location.push_fragment >= 0)
{
if (refl.location.push_vertex >= 0)
glUniform1f(refl.location.push_vertex, value);
if (refl.location.push_fragment >= 0)
glUniform1f(refl.location.push_fragment, value);
if (refl->location.push_vertex >= 0)
glUniform1f(refl->location.push_vertex, value);
if (refl->location.push_fragment >= 0)
glUniform1f(refl->location.push_fragment, value);
}
else
*reinterpret_cast<float *>(push_constant_buffer.data() + refl.push_constant_offset) = value;
*reinterpret_cast<float *>(push_constant_buffer.data() + refl->push_constant_offset) = value;
}
}
@ -1448,13 +1459,11 @@ void Pass::build_semantic_texture_array_vec4(uint8_t *data, slang_texture_semant
glUniform4fv(refl[index].location.ubo_fragment, 1, v4);
}
else
{
build_vec4(
reinterpret_cast<float *>(data + refl[index].ubo_offset),
width,
height);
}
}
if (refl[index].push_constant)
{
@ -1468,13 +1477,11 @@ void Pass::build_semantic_texture_array_vec4(uint8_t *data, slang_texture_semant
glUniform4fv(refl[index].location.push_fragment, 1, v4);
}
else
{
build_vec4(
reinterpret_cast<float *>(push_constant_buffer.data() + refl[index].push_constant_offset),
width,
height);
}
}
}
void Pass::build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic semantic,
@ -1549,87 +1556,85 @@ void Pass::build_semantic_texture_array(uint8_t *buffer,
void Pass::build_semantics(uint8_t *buffer,
const float *mvp, const Texture &original, const Texture &source)
{
unsigned i;
/* MVP */
if (buffer && reflection.semantics[SLANG_SEMANTIC_MVP].uniform)
{
size_t offset = reflection.semantics[SLANG_SEMANTIC_MVP].ubo_offset;
size_t offset = reflection.semantics[
SLANG_SEMANTIC_MVP].ubo_offset;
if (mvp)
memcpy(buffer + offset, mvp, sizeof(float) * 16);
memcpy(buffer + offset,
mvp, sizeof(float) * 16);
else
build_default_matrix(reinterpret_cast<float *>(buffer + offset));
build_default_matrix(reinterpret_cast<float *>(
buffer + offset));
}
if (reflection.semantics[SLANG_SEMANTIC_MVP].push_constant)
{
size_t offset = reflection.semantics[SLANG_SEMANTIC_MVP].push_constant_offset;
size_t offset = reflection.semantics[
SLANG_SEMANTIC_MVP].push_constant_offset;
if (mvp)
memcpy(push_constant_buffer.data() + offset, mvp, sizeof(float) * 16);
memcpy(push_constant_buffer.data() + offset,
mvp, sizeof(float) * 16);
else
build_default_matrix(reinterpret_cast<float *>(push_constant_buffer.data() + offset));
build_default_matrix(reinterpret_cast<float *>(
push_constant_buffer.data() + offset));
}
/* Output information */
build_semantic_vec4(buffer, SLANG_SEMANTIC_OUTPUT,
current_framebuffer_size.width, current_framebuffer_size.height);
current_framebuffer_size.width,
current_framebuffer_size.height);
build_semantic_vec4(buffer, SLANG_SEMANTIC_FINAL_VIEWPORT,
unsigned(current_viewport.width), unsigned(current_viewport.height));
unsigned(current_viewport.width),
unsigned(current_viewport.height));
build_semantic_uint(buffer, SLANG_SEMANTIC_FRAME_COUNT,
frame_count_period ? uint32_t(frame_count % frame_count_period) : uint32_t(frame_count));
frame_count_period
? uint32_t(frame_count % frame_count_period)
: uint32_t(frame_count));
/* Standard inputs */
build_semantic_texture(buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL, original);
build_semantic_texture(buffer, SLANG_TEXTURE_SEMANTIC_SOURCE, source);
/* ORIGINAL_HISTORY[0] is an alias of ORIGINAL. */
build_semantic_texture_array(buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY, 0, original);
build_semantic_texture_array(buffer,
SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY, 0, original);
/* Parameters. */
for (auto &param : filtered_parameters)
{
float value = common->shader_preset->parameters[param.index].current;
build_semantic_parameter(buffer, param.semantic_index, value);
}
for (i = 0; i < filtered_parameters.size(); i++)
build_semantic_parameter(buffer,
filtered_parameters[i].semantic_index,
common->shader_preset->parameters[
filtered_parameters[i].index].current);
/* Previous inputs. */
unsigned i = 0;
for (auto &texture : common->original_history)
{
for (i = 0; i < common->original_history.size(); i++)
build_semantic_texture_array(buffer,
SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY, i + 1,
texture);
i++;
}
common->original_history[i]);
/* Previous passes. */
i = 0;
for (auto &texture : common->pass_outputs)
{
for (i = 0; i < common->pass_outputs.size(); i++)
build_semantic_texture_array(buffer,
SLANG_TEXTURE_SEMANTIC_PASS_OUTPUT, i,
texture);
i++;
}
common->pass_outputs[i]);
/* Feedback FBOs. */
i = 0;
for (auto &texture : common->framebuffer_feedback)
{
for (i = 0; i < common->framebuffer_feedback.size(); i++)
build_semantic_texture_array(buffer,
SLANG_TEXTURE_SEMANTIC_PASS_FEEDBACK, i,
texture);
i++;
}
common->framebuffer_feedback[i]);
/* LUTs. */
i = 0;
for (auto &lut : common->luts)
{
for (i = 0; i < common->luts.size(); i++)
build_semantic_texture_array(buffer,
SLANG_TEXTURE_SEMANTIC_USER, i,
lut->get_texture());
i++;
}
common->luts[i]->get_texture());
}
void Pass::build_commands(
@ -1639,16 +1644,15 @@ void Pass::build_commands(
const float *mvp)
{
current_viewport = vp;
auto size = get_output_size(
Size2D size = get_output_size(
{ original.texture.width, original.texture.height },
{ source.texture.width, source.texture.height });
if (framebuffer &&
(size.width != framebuffer->get_size().width ||
size.height != framebuffer->get_size().height))
{
framebuffer->set_size(size);
}
current_framebuffer_size = size;
glUseProgram(pipeline);
@ -1656,35 +1660,39 @@ void Pass::build_commands(
build_semantics(uniforms.data(), mvp, original, source);
if (locations.flat_ubo_vertex >= 0)
{
glUniform4fv(locations.flat_ubo_vertex,
GLsizei((reflection.ubo_size + 15) / 16),
reinterpret_cast<const float *>(uniforms.data()));
}
if (locations.flat_ubo_fragment >= 0)
{
glUniform4fv(locations.flat_ubo_fragment,
GLsizei((reflection.ubo_size + 15) / 16),
reinterpret_cast<const float *>(uniforms.data()));
}
if (locations.flat_push_vertex >= 0)
{
glUniform4fv(locations.flat_push_vertex,
GLsizei((reflection.push_constant_size + 15) / 16),
reinterpret_cast<const float *>(push_constant_buffer.data()));
}
if (locations.flat_push_fragment >= 0)
{
glUniform4fv(locations.flat_push_fragment,
GLsizei((reflection.push_constant_size + 15) / 16),
reinterpret_cast<const float *>(push_constant_buffer.data()));
}
ubo_ring.update_and_bind(locations.buffer_index_ubo_vertex, locations.buffer_index_ubo_fragment,
uniforms.data(), reflection.ubo_size);
if (!( locations.buffer_index_ubo_vertex == GL_INVALID_INDEX
&& locations.buffer_index_ubo_fragment == GL_INVALID_INDEX))
{
ubo_ring_update_and_bind(
locations.buffer_index_ubo_vertex,
locations.buffer_index_ubo_fragment,
uniforms.data(), reflection.ubo_size,
ubo_ring.buffers[ubo_ring.buffer_index]
);
ubo_ring.buffer_index++;
if (ubo_ring.buffer_index >= ubo_ring.buffers.size())
ubo_ring.buffer_index = 0;
}
/* The final pass is always executed inside
* another render pass since the frontend will
@ -1699,14 +1707,10 @@ void Pass::build_commands(
}
if (final_pass)
{
glViewport(current_viewport.x, current_viewport.y,
current_viewport.width, current_viewport.height);
}
else
{
glViewport(0, 0, size.width, size.height);
}
#ifndef HAVE_OPENGLES3
if (framebuffer && framebuffer->get_format() == GL_SRGB8_ALPHA8)
@ -1723,10 +1727,8 @@ void Pass::build_commands(
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (!final_pass)
{
if (framebuffer->get_levels() > 1)
framebuffer->generate_mips();
}
}
}
@ -1734,10 +1736,7 @@ void Pass::build_commands(
struct gl_core_filter_chain
{
public:
gl_core_filter_chain(unsigned num_passes)
{
set_num_passes(num_passes);
}
gl_core_filter_chain(unsigned num_passes) { set_num_passes(num_passes); }
inline void set_shader_preset(unique_ptr<video_shader> shader)
{
@ -1795,7 +1794,7 @@ void gl_core_filter_chain::clear_history_and_feedback()
texture->clear();
for (auto &pass : passes)
{
auto *fb = pass->get_feedback_framebuffer();
gl_core::Framebuffer *fb = pass->get_feedback_framebuffer();
if (fb)
fb->clear();
}
@ -1803,44 +1802,55 @@ void gl_core_filter_chain::clear_history_and_feedback()
void gl_core_filter_chain::update_history_info()
{
unsigned i = 0;
for (auto &texture : original_history)
unsigned i;
for (i = 0; i < original_history.size(); i++)
{
auto &source = common.original_history[i];
source.texture.image = texture->get_image();
source.texture.width = texture->get_size().width;
source.texture.height = texture->get_size().height;
source.filter = passes.front()->get_source_filter();
source.mip_filter = passes.front()->get_mip_filter();
source.address = passes.front()->get_address_mode();
i++;
gl_core::Texture *source = (gl_core::Texture*)
&common.original_history[i];
if (!source)
continue;
source->texture.image = original_history[i]->get_image();
source->texture.width = original_history[i]->get_size().width;
source->texture.height = original_history[i]->get_size().height;
source->filter = passes.front()->get_source_filter();
source->mip_filter = passes.front()->get_mip_filter();
source->address = passes.front()->get_address_mode();
}
}
void gl_core_filter_chain::update_feedback_info()
{
unsigned i;
if (common.framebuffer_feedback.empty())
return;
for (unsigned i = 0; i < passes.size() - 1; i++)
for (i = 0; i < passes.size() - 1; i++)
{
auto fb = passes[i]->get_feedback_framebuffer();
gl_core::Framebuffer *fb = passes[i]->get_feedback_framebuffer();
if (!fb)
continue;
auto &source = common.framebuffer_feedback[i];
source.texture.image = fb->get_image();
source.texture.width = fb->get_size().width;
source.texture.height = fb->get_size().height;
source.filter = passes[i]->get_source_filter();
source.mip_filter = passes[i]->get_mip_filter();
source.address = passes[i]->get_address_mode();
gl_core::Texture *source = (gl_core::Texture*)
&common.framebuffer_feedback[i];
if (!source)
continue;
source->texture.image = fb->get_image();
source->texture.width = fb->get_size().width;
source->texture.height = fb->get_size().height;
source->filter = passes[i]->get_source_filter();
source->mip_filter = passes[i]->get_mip_filter();
source->address = passes[i]->get_address_mode();
}
}
void gl_core_filter_chain::build_offscreen_passes(const gl_core_viewport &vp)
{
/* First frame, make sure our history and feedback textures are in a clean state. */
/* First frame, make sure our history and feedback textures
* are in a clean state. */
if (require_clear)
{
clear_history_and_feedback();
@ -1863,6 +1873,7 @@ void gl_core_filter_chain::build_offscreen_passes(const gl_core_viewport &vp)
passes[i]->build_commands(original, source, vp, nullptr);
auto &fb = passes[i]->get_framebuffer();
source.texture.image = fb.get_image();
source.texture.width = fb.get_size().width;
source.texture.height = fb.get_size().height;
@ -1883,9 +1894,7 @@ void gl_core_filter_chain::update_history()
if (input_texture.width != tmp->get_size().width ||
input_texture.height != tmp->get_size().height ||
(input_texture.format != 0 && input_texture.format != tmp->get_format()))
{
tmp->set_size({ input_texture.width, input_texture.height }, input_texture.format);
}
tmp->copy(common, input_texture.image);
@ -1901,14 +1910,13 @@ void gl_core_filter_chain::end_frame()
* pass is the last that reads from
* the history and dispatch the copy earlier. */
if (!original_history.empty())
{
update_history();
}
}
void gl_core_filter_chain::build_viewport_pass(
const gl_core_viewport &vp, const float *mvp)
{
unsigned i;
/* First frame, make sure our history and feedback textures are in a clean state. */
if (require_clear)
{
@ -1947,22 +1955,23 @@ void gl_core_filter_chain::build_viewport_pass(
passes.back()->build_commands(original, source, vp, mvp);
/* For feedback FBOs, swap current and previous. */
for (auto &pass : passes)
pass->end_frame();
for (i = 0; i < passes.size(); i++)
passes[i]->end_frame();
}
bool gl_core_filter_chain::init_history()
{
unsigned i;
size_t required_images = 0;
original_history.clear();
common.original_history.clear();
size_t required_images = 0;
for (auto &pass : passes)
{
for (i = 0; i < passes.size(); i++)
required_images =
max(required_images,
pass->get_reflection().semantic_textures[SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY].size());
}
passes[i]->get_reflection().semantic_textures[
SLANG_TEXTURE_SEMANTIC_ORIGINAL_HISTORY].size());
if (required_images < 2)
{
@ -1976,10 +1985,8 @@ bool gl_core_filter_chain::init_history()
original_history.reserve(required_images);
common.original_history.resize(required_images);
for (unsigned i = 0; i < required_images; i++)
{
for (i = 0; i < required_images; i++)
original_history.emplace_back(new gl_core::Framebuffer(0, 1));
}
RARCH_LOG("[GLCore]: Using history of %u frames.\n", unsigned(required_images));
@ -1993,12 +2000,13 @@ bool gl_core_filter_chain::init_history()
bool gl_core_filter_chain::init_feedback()
{
common.framebuffer_feedback.clear();
unsigned i;
bool use_feedbacks = false;
common.framebuffer_feedback.clear();
/* Final pass cannot have feedback. */
for (unsigned i = 0; i < passes.size() - 1; i++)
for (i = 0; i < passes.size() - 1; i++)
{
bool use_feedback = false;
for (auto &pass : passes)
@ -2085,9 +2093,12 @@ void gl_core_filter_chain::set_pass_info(unsigned pass, const gl_core_filter_cha
void gl_core_filter_chain::set_num_passes(unsigned num_passes)
{
unsigned i;
pass_info.resize(num_passes);
passes.reserve(num_passes);
for (unsigned i = 0; i < num_passes; i++)
for (i = 0; i < num_passes; i++)
{
passes.emplace_back(new gl_core::Pass(i + 1 == num_passes));
passes.back()->set_common_resources(&common);
@ -2107,10 +2118,12 @@ void gl_core_filter_chain::add_parameter(unsigned pass, unsigned index, const st
bool gl_core_filter_chain::init()
{
unsigned i;
if (!init_alias())
return false;
for (unsigned i = 0; i < passes.size(); i++)
for (i = 0; i < passes.size(); i++)
{
auto &pass = passes[i];
RARCH_LOG("[slang]: Building pass #%u (%s)\n", i,
@ -2137,8 +2150,8 @@ void gl_core_filter_chain::set_input_texture(
{
input_texture = texture;
// Need a copy to remove padding.
// GL HW render interface in libretro is kinda garbage now ...
/* Need a copy to remove padding.
* GL HW render interface in libretro is kinda garbage now ... */
if (input_texture.padded_width != input_texture.width ||
input_texture.padded_height != input_texture.height)
{
@ -2148,9 +2161,7 @@ void gl_core_filter_chain::set_input_texture(
if (input_texture.width != copy_framebuffer->get_size().width ||
input_texture.height != copy_framebuffer->get_size().height ||
(input_texture.format != 0 && input_texture.format != copy_framebuffer->get_format()))
{
copy_framebuffer->set_size({ input_texture.width, input_texture.height }, input_texture.format);
}
copy_framebuffer->copy_partial(common, input_texture.image,
float(input_texture.width) / input_texture.padded_width,
@ -2184,6 +2195,7 @@ static unique_ptr<gl_core::StaticTexture> gl_core_filter_chain_load_lut(
gl_core_filter_chain *chain,
const video_shader_lut *shader)
{
GLuint tex = 0;
texture_image image = {};
image.supports_rgba = true;
@ -2191,7 +2203,7 @@ static unique_ptr<gl_core::StaticTexture> gl_core_filter_chain_load_lut(
return {};
unsigned levels = shader->mipmap ? gl_core::num_miplevels(image.width, image.height) : 1;
GLuint tex = 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexStorage2D(GL_TEXTURE_2D, levels,
@ -2222,7 +2234,8 @@ static bool gl_core_filter_chain_load_luts(
gl_core_filter_chain *chain,
video_shader *shader)
{
for (unsigned i = 0; i < shader->luts; i++)
unsigned i;
for (i = 0; i < shader->luts; i++)
{
auto image = gl_core_filter_chain_load_lut(chain, &shader->lut[i]);
if (!image)