mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-19 00:41:53 +00:00
Add support for shader pass feedback.
This commit is contained in:
parent
2fdaa89a81
commit
aee5e74001
395
gfx/drivers/gl.c
395
gfx/drivers/gl.c
@ -429,109 +429,128 @@ static void gl_compute_fbo_geometry(gl_t *gl, unsigned width, unsigned height,
|
||||
}
|
||||
}
|
||||
|
||||
static void gl_create_fbo_textures(gl_t *gl)
|
||||
static void gl_create_fbo_texture(gl_t *gl, unsigned i, GLuint texture)
|
||||
{
|
||||
int i;
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
enum gfx_wrap_type wrap;
|
||||
GLenum min_filter, mag_filter, wrap_enum;
|
||||
bool mipmapped = false;
|
||||
bool smooth = false;
|
||||
bool fp_fbo, srgb_fbo;
|
||||
|
||||
GLuint base_filt = settings->video.smooth ? GL_LINEAR : GL_NEAREST;
|
||||
GLuint base_mip_filt = settings->video.smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
mipmapped = gl->shader->mipmap_input(i + 2);
|
||||
|
||||
min_filter = mipmapped ? base_mip_filt : base_filt;
|
||||
if (gl->shader->filter_type(i + 2, &smooth))
|
||||
{
|
||||
min_filter = mipmapped ? (smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
: (smooth ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
|
||||
mag_filter = min_filter_to_mag(min_filter);
|
||||
|
||||
wrap = gl->shader->wrap_type(i + 2);
|
||||
wrap_enum = gl_wrap_type_to_enum(wrap);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_enum);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_enum);
|
||||
|
||||
fp_fbo = gl->fbo_scale[i].fp_fbo;
|
||||
srgb_fbo = gl->fbo_scale[i].srgb_fbo;
|
||||
|
||||
if (fp_fbo)
|
||||
{
|
||||
if (!gl->has_fp_fbo)
|
||||
RARCH_ERR("[GL]: Floating-point FBO was requested, but is not supported. Falling back to UNORM. Result may band/clip/etc.!\n");
|
||||
}
|
||||
else if (srgb_fbo)
|
||||
{
|
||||
if (!gl->has_srgb_fbo)
|
||||
RARCH_ERR("[GL]: sRGB FBO was requested, but it is not supported. Falling back to UNORM. Result may have banding!\n");
|
||||
}
|
||||
|
||||
if (settings->video.force_srgb_disable)
|
||||
srgb_fbo = false;
|
||||
|
||||
#ifndef HAVE_OPENGLES2
|
||||
if (fp_fbo && gl->has_fp_fbo)
|
||||
{
|
||||
RARCH_LOG("[GL]: FBO pass #%d is floating-point.\n", i);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height,
|
||||
0, GL_RGBA, GL_FLOAT, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef HAVE_OPENGLES
|
||||
settings_t *settings = config_get_ptr();
|
||||
GLuint base_filt = settings->video.smooth ? GL_LINEAR : GL_NEAREST;
|
||||
GLuint base_mip_filt = settings->video.smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST;
|
||||
|
||||
if (srgb_fbo && gl->has_srgb_fbo)
|
||||
{
|
||||
RARCH_LOG("[GL]: FBO pass #%d is sRGB.\n", i);
|
||||
#ifdef HAVE_OPENGLES2
|
||||
/* EXT defines are same as core GLES3 defines,
|
||||
* but GLES3 variant requires different arguments. */
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_SRGB_ALPHA_EXT,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
gl->has_srgb_fbo_gles3 ? GL_RGBA : GL_SRGB_ALPHA_EXT,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_SRGB8_ALPHA8,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_OPENGLES2
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_RGBA,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
#else
|
||||
/* Avoid potential performance
|
||||
* reductions on particular platforms. */
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, RARCH_GL_INTERNAL_FORMAT32,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gl_create_fbo_textures(gl_t *gl)
|
||||
{
|
||||
int i;
|
||||
glGenTextures(gl->fbo_pass, gl->fbo_texture);
|
||||
|
||||
for (i = 0; i < gl->fbo_pass; i++)
|
||||
{
|
||||
enum gfx_wrap_type wrap;
|
||||
GLenum min_filter, mag_filter, wrap_enum;
|
||||
bool mipmapped = false;
|
||||
bool smooth = false;
|
||||
bool fp_fbo, srgb_fbo;
|
||||
gl_create_fbo_texture(gl, i, gl->fbo_texture[i]);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i]);
|
||||
|
||||
mipmapped = gl->shader->mipmap_input(i + 2);
|
||||
|
||||
min_filter = mipmapped ? base_mip_filt : base_filt;
|
||||
if (gl->shader->filter_type(i + 2, &smooth))
|
||||
min_filter = mipmapped ? (smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
: (smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
mag_filter = min_filter_to_mag(min_filter);
|
||||
|
||||
wrap = gl->shader->wrap_type(i + 2);
|
||||
wrap_enum = gl_wrap_type_to_enum(wrap);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_enum);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_enum);
|
||||
|
||||
fp_fbo = gl->fbo_scale[i].fp_fbo;
|
||||
srgb_fbo = gl->fbo_scale[i].srgb_fbo;
|
||||
|
||||
if (fp_fbo)
|
||||
{
|
||||
if (!gl->has_fp_fbo)
|
||||
RARCH_ERR("[GL]: Floating-point FBO was requested, but is not supported. Falling back to UNORM. Result may band/clip/etc.!\n");
|
||||
}
|
||||
else if (srgb_fbo)
|
||||
{
|
||||
if (!gl->has_srgb_fbo)
|
||||
RARCH_ERR("[GL]: sRGB FBO was requested, but it is not supported. Falling back to UNORM. Result may have banding!\n");
|
||||
}
|
||||
|
||||
if (settings->video.force_srgb_disable)
|
||||
srgb_fbo = false;
|
||||
|
||||
#ifndef HAVE_OPENGLES2
|
||||
if (fp_fbo && gl->has_fp_fbo)
|
||||
{
|
||||
RARCH_LOG("[GL]: FBO pass #%d is floating-point.\n", i);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height,
|
||||
0, GL_RGBA, GL_FLOAT, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef HAVE_OPENGLES
|
||||
if (srgb_fbo && gl->has_srgb_fbo)
|
||||
{
|
||||
RARCH_LOG("[GL]: FBO pass #%d is sRGB.\n", i);
|
||||
#ifdef HAVE_OPENGLES2
|
||||
/* EXT defines are same as core GLES3 defines,
|
||||
* but GLES3 variant requires different arguments. */
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_SRGB_ALPHA_EXT,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
gl->has_srgb_fbo_gles3 ? GL_RGBA : GL_SRGB_ALPHA_EXT,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_SRGB8_ALPHA8,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_OPENGLES2
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_RGBA,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
#else
|
||||
/* Avoid potential performance
|
||||
* reductions on particular platforms. */
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, RARCH_GL_INTERNAL_FORMAT32,
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height, 0,
|
||||
RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (gl->fbo_feedback_enable)
|
||||
{
|
||||
glGenTextures(1, &gl->fbo_feedback_texture);
|
||||
gl_create_fbo_texture(gl, gl->fbo_feedback_pass, gl->fbo_feedback_texture);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -545,10 +564,10 @@ static bool gl_create_fbo_targets(gl_t *gl)
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glGenFramebuffers(gl->fbo_pass, gl->fbo);
|
||||
GLenum status;
|
||||
|
||||
for (i = 0; i < gl->fbo_pass; i++)
|
||||
{
|
||||
GLenum status;
|
||||
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo[i]);
|
||||
glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER,
|
||||
RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->fbo_texture[i], 0);
|
||||
@ -558,10 +577,28 @@ static bool gl_create_fbo_targets(gl_t *gl)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (gl->fbo_feedback_texture)
|
||||
{
|
||||
glGenFramebuffers(1, &gl->fbo_feedback);
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo_feedback);
|
||||
glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER,
|
||||
RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->fbo_feedback_texture, 0);
|
||||
|
||||
status = glCheckFramebufferStatus(RARCH_GL_FRAMEBUFFER);
|
||||
if (status != RARCH_GL_FRAMEBUFFER_COMPLETE)
|
||||
goto error;
|
||||
|
||||
/* Make sure the feedback textures are cleared so we don't feedback noise. */
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
glDeleteFramebuffers(gl->fbo_pass, gl->fbo);
|
||||
if (gl->fbo_feedback)
|
||||
glDeleteFramebuffers(1, &gl->fbo_feedback);
|
||||
RARCH_ERR("Failed to set up frame buffer objects. Multi-pass shading will not work.\n");
|
||||
return false;
|
||||
}
|
||||
@ -577,6 +614,16 @@ static void gl_deinit_fbo(gl_t *gl)
|
||||
memset(gl->fbo, 0, sizeof(gl->fbo));
|
||||
gl->fbo_inited = false;
|
||||
gl->fbo_pass = 0;
|
||||
|
||||
if (gl->fbo_feedback)
|
||||
glDeleteFramebuffers(1, &gl->fbo_feedback);
|
||||
if (gl->fbo_feedback_texture)
|
||||
glDeleteTextures(1, &gl->fbo_feedback_texture);
|
||||
|
||||
gl->fbo_feedback_enable = false;
|
||||
gl->fbo_feedback_pass = -1;
|
||||
gl->fbo_feedback_texture = 0;
|
||||
gl->fbo_feedback = 0;
|
||||
}
|
||||
|
||||
/* Set up render to texture. */
|
||||
@ -642,6 +689,20 @@ static void gl_init_fbo(gl_t *gl, unsigned fbo_width, unsigned fbo_height)
|
||||
gl->fbo_rect[i].width, gl->fbo_rect[i].height);
|
||||
}
|
||||
|
||||
gl->fbo_feedback_enable = gl->shader->get_feedback_pass(&gl->fbo_feedback_pass);
|
||||
|
||||
if (gl->fbo_feedback_enable && gl->fbo_feedback_pass < (unsigned)gl->fbo_pass)
|
||||
{
|
||||
RARCH_LOG("[GL]: Creating feedback FBO %d @ %ux%u\n", i,
|
||||
gl->fbo_rect[gl->fbo_feedback_pass].width, gl->fbo_rect[gl->fbo_feedback_pass].height);
|
||||
}
|
||||
else if (gl->fbo_feedback_enable)
|
||||
{
|
||||
RARCH_WARN("[GL]: Tried to create feedback FBO of pass #%u, but there are only %d FBO passes. Will use input texture as feedback texture.\n",
|
||||
gl->fbo_feedback_pass, gl->fbo_pass);
|
||||
gl->fbo_feedback_enable = false;
|
||||
}
|
||||
|
||||
gl_create_fbo_textures(gl);
|
||||
if (!gl_create_fbo_targets(gl))
|
||||
{
|
||||
@ -918,42 +979,35 @@ static INLINE void gl_start_frame_fbo(gl_t *gl)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* On resize, we might have to recreate our FBOs
|
||||
* due to "Viewport" scale, and set a new viewport. */
|
||||
|
||||
static void gl_check_fbo_dimensions(gl_t *gl)
|
||||
static void gl_check_fbo_dimension(gl_t *gl, unsigned i, GLuint fbo, GLuint texture, bool update_feedback)
|
||||
{
|
||||
int i;
|
||||
GLenum status;
|
||||
unsigned img_width, img_height, max, pow2_size;
|
||||
bool check_dimensions = false;
|
||||
struct gfx_fbo_rect *fbo_rect = &gl->fbo_rect[i];
|
||||
|
||||
if (!fbo_rect)
|
||||
return;
|
||||
|
||||
check_dimensions =
|
||||
(fbo_rect->max_img_width > fbo_rect->width) ||
|
||||
(fbo_rect->max_img_height > fbo_rect->height);
|
||||
|
||||
if (!check_dimensions)
|
||||
return;
|
||||
|
||||
/* Check proactively since we might suddently
|
||||
* get sizes of tex_w width or tex_h height. */
|
||||
img_width = fbo_rect->max_img_width;
|
||||
img_height = fbo_rect->max_img_height;
|
||||
max = img_width > img_height ? img_width : img_height;
|
||||
pow2_size = next_pow2(max);
|
||||
|
||||
fbo_rect->width = fbo_rect->height = pow2_size;
|
||||
|
||||
/* Check if we have to recreate our FBO textures. */
|
||||
for (i = 0; i < gl->fbo_pass; i++)
|
||||
{
|
||||
GLenum status;
|
||||
unsigned img_width, img_height, max, pow2_size;
|
||||
bool check_dimensions = false;
|
||||
struct gfx_fbo_rect *fbo_rect = &gl->fbo_rect[i];
|
||||
|
||||
if (!fbo_rect)
|
||||
continue;
|
||||
|
||||
check_dimensions =
|
||||
(fbo_rect->max_img_width > fbo_rect->width) ||
|
||||
(fbo_rect->max_img_height > fbo_rect->height);
|
||||
|
||||
if (!check_dimensions)
|
||||
continue;
|
||||
|
||||
/* Check proactively since we might suddently
|
||||
* get sizes of tex_w width or tex_h height. */
|
||||
img_width = fbo_rect->max_img_width;
|
||||
img_height = fbo_rect->max_img_height;
|
||||
max = img_width > img_height ? img_width : img_height;
|
||||
pow2_size = next_pow2(max);
|
||||
|
||||
fbo_rect->width = fbo_rect->height = pow2_size;
|
||||
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo[i]);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->fbo_texture[i]);
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, fbo);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, RARCH_GL_INTERNAL_FORMAT32,
|
||||
@ -964,19 +1018,62 @@ static void gl_check_fbo_dimensions(gl_t *gl)
|
||||
|
||||
glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER,
|
||||
RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
gl->fbo_texture[i], 0);
|
||||
texture, 0);
|
||||
|
||||
status = glCheckFramebufferStatus(RARCH_GL_FRAMEBUFFER);
|
||||
if (status != RARCH_GL_FRAMEBUFFER_COMPLETE)
|
||||
RARCH_WARN("Failed to reinitialize FBO texture.\n");
|
||||
}
|
||||
|
||||
RARCH_LOG("[GL]: Recreating FBO texture #%d: %ux%u\n",
|
||||
i, fbo_rect->width, fbo_rect->height);
|
||||
/* Update feedback texture in-place so we avoid having to juggle two different fbo_rect structs since they get updated here. */
|
||||
if (update_feedback)
|
||||
{
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->fbo_feedback);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->fbo_feedback_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, RARCH_GL_INTERNAL_FORMAT32,
|
||||
fbo_rect->width,
|
||||
fbo_rect->height,
|
||||
0, RARCH_GL_TEXTURE_TYPE32,
|
||||
RARCH_GL_FORMAT32, NULL);
|
||||
|
||||
glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER,
|
||||
RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
gl->fbo_feedback_texture, 0);
|
||||
|
||||
status = glCheckFramebufferStatus(RARCH_GL_FRAMEBUFFER);
|
||||
if (status != RARCH_GL_FRAMEBUFFER_COMPLETE)
|
||||
RARCH_WARN("Failed to reinitialize FBO texture.\n");
|
||||
else
|
||||
{
|
||||
/* Make sure the feedback textures are cleared so we don't feedback noise. */
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
RARCH_LOG("[GL]: Recreating FBO texture #%d: %ux%u\n",
|
||||
i, fbo_rect->width, fbo_rect->height);
|
||||
}
|
||||
|
||||
/* On resize, we might have to recreate our FBOs
|
||||
* due to "Viewport" scale, and set a new viewport. */
|
||||
|
||||
static void gl_check_fbo_dimensions(gl_t *gl)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check if we have to recreate our FBO textures. */
|
||||
for (i = 0; i < gl->fbo_pass; i++)
|
||||
{
|
||||
bool update_feedback = gl->fbo_feedback_enable && (unsigned)i == gl->fbo_feedback_pass;
|
||||
gl_check_fbo_dimension(gl, i, gl->fbo[i], gl->fbo_texture[i], update_feedback);
|
||||
}
|
||||
}
|
||||
|
||||
static void gl_frame_fbo(gl_t *gl, uint64_t frame_count,
|
||||
const struct gfx_tex_info *tex_info)
|
||||
const struct gfx_tex_info *tex_info, const struct gfx_tex_info *feedback_info)
|
||||
{
|
||||
unsigned width, height;
|
||||
const struct gfx_fbo_rect *prev_rect;
|
||||
@ -1029,7 +1126,7 @@ static void gl_frame_fbo(gl_t *gl, uint64_t frame_count,
|
||||
gl->shader->set_params(gl, prev_rect->img_width, prev_rect->img_height,
|
||||
prev_rect->width, prev_rect->height,
|
||||
gl->vp.width, gl->vp.height, (unsigned int)frame_count,
|
||||
tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
|
||||
tex_info, gl->prev_info, feedback_info, fbo_tex_info, fbo_tex_info_cnt);
|
||||
|
||||
gl->coords.vertices = 4;
|
||||
gl->shader->set_coords(&gl->coords);
|
||||
@ -1076,7 +1173,7 @@ static void gl_frame_fbo(gl_t *gl, uint64_t frame_count,
|
||||
prev_rect->img_width, prev_rect->img_height,
|
||||
prev_rect->width, prev_rect->height,
|
||||
gl->vp.width, gl->vp.height, (unsigned int)frame_count,
|
||||
tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt);
|
||||
tex_info, gl->prev_info, feedback_info, fbo_tex_info, fbo_tex_info_cnt);
|
||||
|
||||
gl->coords.vertex = gl->vertex_ptr;
|
||||
|
||||
@ -1417,6 +1514,17 @@ static INLINE void gl_set_prev_texture(gl_t *gl,
|
||||
sizeof(*tex_info) * (gl->textures - 1));
|
||||
memcpy(&gl->prev_info[0], tex_info,
|
||||
sizeof(*tex_info));
|
||||
|
||||
/* Implement feedback by swapping out FBO/textures for FBO pass #N and feedbacks. */
|
||||
if (gl->fbo_feedback_enable)
|
||||
{
|
||||
GLuint tmp_fbo = gl->fbo_feedback;
|
||||
GLuint tmp_tex = gl->fbo_feedback_texture;
|
||||
gl->fbo_feedback = gl->fbo[gl->fbo_feedback_pass];
|
||||
gl->fbo_feedback_texture = gl->fbo_texture[gl->fbo_feedback_pass];
|
||||
gl->fbo[gl->fbo_feedback_pass] = tmp_fbo;
|
||||
gl->fbo_texture[gl->fbo_feedback_pass] = tmp_tex;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void gl_set_shader_viewport(gl_t *gl, unsigned shader)
|
||||
@ -1633,6 +1741,22 @@ static bool gl_frame(void *data, const void *frame,
|
||||
gl->tex_info.tex_size[0] = gl->tex_w;
|
||||
gl->tex_info.tex_size[1] = gl->tex_h;
|
||||
|
||||
struct gfx_tex_info feedback_info = gl->tex_info;
|
||||
if (gl->fbo_feedback_enable)
|
||||
{
|
||||
const struct gfx_fbo_rect *rect = &gl->fbo_rect[gl->fbo_feedback_pass];
|
||||
GLfloat xamt = (GLfloat)rect->img_width / rect->width;
|
||||
GLfloat yamt = (GLfloat)rect->img_height / rect->height;
|
||||
|
||||
feedback_info.tex = gl->fbo_feedback_texture;
|
||||
feedback_info.input_size[0] = rect->img_width;
|
||||
feedback_info.input_size[1] = rect->img_height;
|
||||
feedback_info.tex_size[0] = rect->width;
|
||||
feedback_info.tex_size[1] = rect->height;
|
||||
|
||||
set_texture_coords(feedback_info.coord, xamt, yamt);
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
gl->shader->set_params(gl,
|
||||
@ -1640,7 +1764,8 @@ static bool gl_frame(void *data, const void *frame,
|
||||
gl->tex_w, gl->tex_h,
|
||||
gl->vp.width, gl->vp.height,
|
||||
(unsigned int)frame_count,
|
||||
&gl->tex_info, gl->prev_info, NULL, 0);
|
||||
&gl->tex_info, gl->prev_info, &feedback_info,
|
||||
NULL, 0);
|
||||
|
||||
gl->coords.vertices = 4;
|
||||
gl->shader->set_coords(&gl->coords);
|
||||
@ -1649,7 +1774,7 @@ static bool gl_frame(void *data, const void *frame,
|
||||
|
||||
#ifdef HAVE_FBO
|
||||
if (gl->fbo_inited)
|
||||
gl_frame_fbo(gl, frame_count, &gl->tex_info);
|
||||
gl_frame_fbo(gl, frame_count, &gl->tex_info, &feedback_info);
|
||||
#endif
|
||||
|
||||
gl_set_prev_texture(gl, &gl->tex_info);
|
||||
|
@ -209,6 +209,11 @@ typedef struct gl
|
||||
int fbo_pass;
|
||||
bool fbo_inited;
|
||||
|
||||
bool fbo_feedback_enable;
|
||||
unsigned fbo_feedback_pass;
|
||||
GLuint fbo_feedback;
|
||||
GLuint fbo_feedback_texture;
|
||||
|
||||
GLuint hw_render_fbo[GFX_MAX_TEXTURES];
|
||||
GLuint hw_render_depth[GFX_MAX_TEXTURES];
|
||||
bool hw_render_fbo_init;
|
||||
|
@ -139,6 +139,7 @@ struct cg_program
|
||||
|
||||
struct cg_fbo_params fbo[GFX_MAX_SHADERS];
|
||||
struct cg_fbo_params orig;
|
||||
struct cg_fbo_params feedback;
|
||||
struct cg_fbo_params prev[PREV_TEXTURES];
|
||||
};
|
||||
|
||||
@ -152,7 +153,7 @@ typedef struct cg_shader_data
|
||||
struct video_shader *shader;
|
||||
state_tracker_t *state_tracker;
|
||||
GLuint lut_textures[GFX_MAX_TEXTURES];
|
||||
CGparameter cg_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
|
||||
CGparameter cg_attribs[PREV_TEXTURES + 2 + 4 + GFX_MAX_SHADERS];
|
||||
char cg_alias_define[GFX_MAX_SHADERS][128];
|
||||
CGcontext cgCtx;
|
||||
} cg_shader_data_t;
|
||||
@ -222,12 +223,40 @@ fallback:
|
||||
#define set_param_1f(param, x) \
|
||||
if (param) cgGLSetParameter1f(param, x)
|
||||
|
||||
static void gl_cg_set_texture_info(cg_shader_data_t *cg, const struct cg_fbo_params *params, const struct gfx_tex_info *info)
|
||||
{
|
||||
CGparameter param = params->tex;
|
||||
if (param)
|
||||
{
|
||||
cgGLSetTextureParameter(param, info->tex);
|
||||
cgGLEnableTextureParameter(param);
|
||||
}
|
||||
|
||||
set_param_2f(params->vid_size_v,
|
||||
info->input_size[0], info->input_size[1]);
|
||||
set_param_2f(params->vid_size_f,
|
||||
info->input_size[0], info->input_size[1]);
|
||||
set_param_2f(params->tex_size_v,
|
||||
info->tex_size[0], info->tex_size[1]);
|
||||
set_param_2f(params->tex_size_f,
|
||||
info->tex_size[0], info->tex_size[1]);
|
||||
|
||||
if (params->coord)
|
||||
{
|
||||
cgGLSetParameterPointer(params->coord, 2,
|
||||
GL_FLOAT, 0, info->coord);
|
||||
cgGLEnableClientState(params->coord);
|
||||
cg->cg_attribs[cg->cg_attrib_idx++] = params->coord;
|
||||
}
|
||||
}
|
||||
|
||||
static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
unsigned tex_width, unsigned tex_height,
|
||||
unsigned out_width, unsigned out_height,
|
||||
unsigned frame_count,
|
||||
const void *_info,
|
||||
const void *_prev_info,
|
||||
const void *_feedback_info,
|
||||
const void *_fbo_info,
|
||||
unsigned fbo_info_cnt)
|
||||
{
|
||||
@ -235,6 +264,7 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
CGparameter param;
|
||||
const struct gfx_tex_info *info = (const struct gfx_tex_info*)_info;
|
||||
const struct gfx_tex_info *prev_info = (const struct gfx_tex_info*)_prev_info;
|
||||
const struct gfx_tex_info *feedback_info = (const struct gfx_tex_info*)_feedback_info;
|
||||
const struct gfx_tex_info *fbo_info = (const struct gfx_tex_info*)_fbo_info;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
@ -269,57 +299,14 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
}
|
||||
|
||||
/* Set orig texture. */
|
||||
param = cg->prg[cg->active_idx].orig.tex;
|
||||
if (param)
|
||||
{
|
||||
cgGLSetTextureParameter(param, info->tex);
|
||||
cgGLEnableTextureParameter(param);
|
||||
}
|
||||
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].orig, info);
|
||||
|
||||
set_param_2f(cg->prg[cg->active_idx].orig.vid_size_v,
|
||||
info->input_size[0], info->input_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].orig.vid_size_f,
|
||||
info->input_size[0], info->input_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].orig.tex_size_v,
|
||||
info->tex_size[0], info->tex_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].orig.tex_size_f,
|
||||
info->tex_size[0], info->tex_size[1]);
|
||||
|
||||
if (cg->prg[cg->active_idx].orig.coord)
|
||||
{
|
||||
cgGLSetParameterPointer(cg->prg[cg->active_idx].orig.coord, 2,
|
||||
GL_FLOAT, 0, info->coord);
|
||||
cgGLEnableClientState(cg->prg[cg->active_idx].orig.coord);
|
||||
cg->cg_attribs[cg->cg_attrib_idx++] = cg->prg[cg->active_idx].orig.coord;
|
||||
}
|
||||
/* Set feedback texture. */
|
||||
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].feedback, feedback_info);
|
||||
|
||||
/* Set prev textures. */
|
||||
for (i = 0; i < PREV_TEXTURES; i++)
|
||||
{
|
||||
param = cg->prg[cg->active_idx].prev[i].tex;
|
||||
if (param)
|
||||
{
|
||||
cgGLSetTextureParameter(param, prev_info[i].tex);
|
||||
cgGLEnableTextureParameter(param);
|
||||
}
|
||||
|
||||
set_param_2f(cg->prg[cg->active_idx].prev[i].vid_size_v,
|
||||
prev_info[i].input_size[0], prev_info[i].input_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].prev[i].vid_size_f,
|
||||
prev_info[i].input_size[0], prev_info[i].input_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].prev[i].tex_size_v,
|
||||
prev_info[i].tex_size[0], prev_info[i].tex_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].prev[i].tex_size_f,
|
||||
prev_info[i].tex_size[0], prev_info[i].tex_size[1]);
|
||||
|
||||
if (cg->prg[cg->active_idx].prev[i].coord)
|
||||
{
|
||||
cgGLSetParameterPointer(cg->prg[cg->active_idx].prev[i].coord,
|
||||
2, GL_FLOAT, 0, prev_info[i].coord);
|
||||
cgGLEnableClientState(cg->prg[cg->active_idx].prev[i].coord);
|
||||
cg->cg_attribs[cg->cg_attrib_idx++] = cg->prg[cg->active_idx].prev[i].coord;
|
||||
}
|
||||
}
|
||||
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].prev[i], &prev_info[i]);
|
||||
|
||||
/* Set lookup textures. */
|
||||
for (i = 0; i < cg->shader->luts; i++)
|
||||
@ -348,32 +335,7 @@ static void gl_cg_set_params(void *data, unsigned width, unsigned height,
|
||||
if (cg->active_idx)
|
||||
{
|
||||
for (i = 0; i < fbo_info_cnt; i++)
|
||||
{
|
||||
if (cg->prg[cg->active_idx].fbo[i].tex)
|
||||
{
|
||||
cgGLSetTextureParameter(
|
||||
cg->prg[cg->active_idx].fbo[i].tex, fbo_info[i].tex);
|
||||
cgGLEnableTextureParameter(cg->prg[cg->active_idx].fbo[i].tex);
|
||||
}
|
||||
|
||||
set_param_2f(cg->prg[cg->active_idx].fbo[i].vid_size_v,
|
||||
fbo_info[i].input_size[0], fbo_info[i].input_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].fbo[i].vid_size_f,
|
||||
fbo_info[i].input_size[0], fbo_info[i].input_size[1]);
|
||||
|
||||
set_param_2f(cg->prg[cg->active_idx].fbo[i].tex_size_v,
|
||||
fbo_info[i].tex_size[0], fbo_info[i].tex_size[1]);
|
||||
set_param_2f(cg->prg[cg->active_idx].fbo[i].tex_size_f,
|
||||
fbo_info[i].tex_size[0], fbo_info[i].tex_size[1]);
|
||||
|
||||
if (cg->prg[cg->active_idx].fbo[i].coord)
|
||||
{
|
||||
cgGLSetParameterPointer(cg->prg[cg->active_idx].fbo[i].coord,
|
||||
2, GL_FLOAT, 0, fbo_info[i].coord);
|
||||
cgGLEnableClientState(cg->prg[cg->active_idx].fbo[i].coord);
|
||||
cg->cg_attribs[cg->cg_attrib_idx++] = cg->prg[cg->active_idx].fbo[i].coord;
|
||||
}
|
||||
}
|
||||
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].fbo[i], &fbo_info[i]);
|
||||
}
|
||||
|
||||
/* #pragma parameters. */
|
||||
@ -850,6 +812,13 @@ static void set_program_attributes(cg_shader_data_t *cg, unsigned i)
|
||||
cg->prg[i].orig.tex_size_f = cgGetNamedParameter(cg->prg[i].fprg, "ORIG.texture_size");
|
||||
cg->prg[i].orig.coord = cgGetNamedParameter(cg->prg[i].vprg, "ORIG.tex_coord");
|
||||
|
||||
cg->prg[i].feedback.tex = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.texture");
|
||||
cg->prg[i].feedback.vid_size_v = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.video_size");
|
||||
cg->prg[i].feedback.vid_size_f = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.video_size");
|
||||
cg->prg[i].feedback.tex_size_v = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.texture_size");
|
||||
cg->prg[i].feedback.tex_size_f = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.texture_size");
|
||||
cg->prg[i].feedback.coord = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.tex_coord");
|
||||
|
||||
if (i > 1)
|
||||
{
|
||||
char pass_str[64] = {0};
|
||||
@ -1081,6 +1050,18 @@ static unsigned gl_cg_get_prev_textures(void)
|
||||
return max_prev;
|
||||
}
|
||||
|
||||
static bool gl_cg_get_feedback_pass(unsigned *pass)
|
||||
{
|
||||
driver_t *driver = driver_get_ptr();
|
||||
cg_shader_data_t *cg = (cg_shader_data_t*)driver->video_shader_data;
|
||||
|
||||
if (!cg || cg->shader->feedback_pass < 0)
|
||||
return false;
|
||||
|
||||
*pass = cg->shader->feedback_pass;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool gl_cg_mipmap_input(unsigned idx)
|
||||
{
|
||||
driver_t *driver = driver_get_ptr();
|
||||
@ -1111,6 +1092,7 @@ const shader_backend_t gl_cg_backend = {
|
||||
gl_cg_set_coords,
|
||||
gl_cg_set_mvp,
|
||||
gl_cg_get_prev_textures,
|
||||
gl_cg_get_feedback_pass,
|
||||
gl_cg_mipmap_input,
|
||||
gl_cg_get_current_shader,
|
||||
|
||||
|
@ -89,6 +89,7 @@ struct shader_uniforms
|
||||
int lut_texture[GFX_MAX_TEXTURES];
|
||||
|
||||
struct shader_uniforms_frame orig;
|
||||
struct shader_uniforms_frame feedback;
|
||||
struct shader_uniforms_frame pass[GFX_MAX_SHADERS];
|
||||
struct shader_uniforms_frame prev[PREV_TEXTURES];
|
||||
};
|
||||
@ -212,7 +213,7 @@ typedef struct glsl_shader_data
|
||||
unsigned gl_attrib_index;
|
||||
GLuint gl_program[GFX_MAX_SHADERS];
|
||||
GLuint gl_teximage[GFX_MAX_TEXTURES];
|
||||
GLint gl_attribs[PREV_TEXTURES + 1 + 4 + GFX_MAX_SHADERS];
|
||||
GLint gl_attribs[PREV_TEXTURES + 2 + 4 + GFX_MAX_SHADERS];
|
||||
state_tracker_t *gl_state_tracker;
|
||||
} glsl_shader_data_t;
|
||||
|
||||
@ -606,6 +607,9 @@ static void find_uniforms(glsl_shader_data_t *glsl,
|
||||
|
||||
clear_uniforms_frame(&uni->orig);
|
||||
find_uniforms_frame(glsl, prog, &uni->orig, "Orig");
|
||||
clear_uniforms_frame(&uni->feedback);
|
||||
find_uniforms_frame(glsl, prog, &uni->feedback, "Feedback");
|
||||
|
||||
if (pass > 1)
|
||||
{
|
||||
snprintf(frame_base, sizeof(frame_base), "PassPrev%u", pass);
|
||||
@ -944,6 +948,7 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
unsigned frame_count,
|
||||
const void *_info,
|
||||
const void *_prev_info,
|
||||
const void *_feedback_info,
|
||||
const void *_fbo_info, unsigned fbo_info_cnt)
|
||||
{
|
||||
GLfloat buffer[512];
|
||||
@ -954,6 +959,7 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
size_t size = 0, attribs_size = 0;
|
||||
const struct gfx_tex_info *info = (const struct gfx_tex_info*)_info;
|
||||
const struct gfx_tex_info *prev_info = (const struct gfx_tex_info*)_prev_info;
|
||||
const struct gfx_tex_info *feedback_info = (const struct gfx_tex_info*)_feedback_info;
|
||||
const struct gfx_tex_info *fbo_info = (const struct gfx_tex_info*)_fbo_info;
|
||||
struct glsl_attrib *attr = (struct glsl_attrib*)attribs;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
@ -1011,9 +1017,9 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
texunit++;
|
||||
}
|
||||
|
||||
/* Set original texture. */
|
||||
if (glsl->glsl_active_index)
|
||||
{
|
||||
/* Set original texture. */
|
||||
if (uni->orig.texture >= 0)
|
||||
{
|
||||
/* Bind original texture. */
|
||||
@ -1042,6 +1048,35 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height,
|
||||
size += 8;
|
||||
}
|
||||
|
||||
/* Set feedback texture. */
|
||||
if (uni->feedback.texture >= 0)
|
||||
{
|
||||
/* Bind original texture. */
|
||||
glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
glUniform1i(uni->feedback.texture, texunit);
|
||||
glBindTexture(GL_TEXTURE_2D, feedback_info->tex);
|
||||
texunit++;
|
||||
}
|
||||
|
||||
if (uni->feedback.texture_size >= 0)
|
||||
glUniform2fv(uni->feedback.texture_size, 1, feedback_info->tex_size);
|
||||
|
||||
if (uni->feedback.input_size >= 0)
|
||||
glUniform2fv(uni->feedback.input_size, 1, feedback_info->input_size);
|
||||
|
||||
/* Pass texture coordinates. */
|
||||
if (uni->feedback.tex_coord >= 0)
|
||||
{
|
||||
attr->loc = uni->feedback.tex_coord;
|
||||
attr->size = 2;
|
||||
attr->offset = size * sizeof(GLfloat);
|
||||
attribs_size++;
|
||||
attr++;
|
||||
|
||||
memcpy(buffer + size, feedback_info->coord, 8 * sizeof(GLfloat));
|
||||
size += 8;
|
||||
}
|
||||
|
||||
/* Bind FBO textures. */
|
||||
for (i = 0; i < fbo_info_cnt; i++)
|
||||
{
|
||||
@ -1350,6 +1385,17 @@ static bool gl_glsl_mipmap_input(unsigned idx)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gl_glsl_get_feedback_pass(unsigned *index)
|
||||
{
|
||||
driver_t *driver = driver_get_ptr();
|
||||
glsl_shader_data_t *glsl = (glsl_shader_data_t*)driver->video_shader_data;
|
||||
if (!glsl || glsl->shader->feedback_pass < 0)
|
||||
return false;
|
||||
|
||||
*index = glsl->shader->feedback_pass;
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct video_shader *gl_glsl_get_current_shader(void)
|
||||
{
|
||||
driver_t *driver = driver_get_ptr();
|
||||
@ -1384,6 +1430,7 @@ const shader_backend_t gl_glsl_backend = {
|
||||
gl_glsl_set_coords,
|
||||
gl_glsl_set_mvp,
|
||||
gl_glsl_get_prev_textures,
|
||||
gl_glsl_get_feedback_pass,
|
||||
gl_glsl_mipmap_input,
|
||||
gl_glsl_get_current_shader,
|
||||
|
||||
|
@ -107,12 +107,14 @@ static void hlsl_set_params(void *data, unsigned width, unsigned height,
|
||||
unsigned frame_counter,
|
||||
const void *_info,
|
||||
const void *_prev_info,
|
||||
const void *_feedback_info,
|
||||
const void *_fbo_info, unsigned fbo_info_cnt)
|
||||
{
|
||||
d3d_video_t *d3d = (d3d_video_t*)data;
|
||||
LPDIRECT3DDEVICE d3d_device_ptr = (LPDIRECT3DDEVICE)d3d->dev;
|
||||
const struct gfx_tex_info *info = (const struct gfx_tex_info*)_info;
|
||||
const struct gfx_tex_info *prev_info = (const struct gfx_tex_info*)_prev_info;
|
||||
(void)_feedback_info;
|
||||
const struct gfx_tex_info *fbo_info = (const struct gfx_tex_info*)_fbo_info;
|
||||
driver_t *driver = driver_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
@ -477,6 +479,12 @@ static bool hlsl_mipmap_input(unsigned idx)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hlsl_get_feedback_pass(unsigned *idx)
|
||||
{
|
||||
(void)idx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct video_shader *hlsl_get_current_shader(void)
|
||||
{
|
||||
return NULL;
|
||||
@ -494,6 +502,7 @@ const shader_backend_t hlsl_backend = {
|
||||
NULL, /* hlsl_set_coords */
|
||||
hlsl_set_mvp,
|
||||
NULL, /* hlsl_get_prev_textures */
|
||||
hlsl_get_feedback_pass,
|
||||
hlsl_mipmap_input,
|
||||
hlsl_get_current_shader,
|
||||
|
||||
|
@ -43,6 +43,7 @@ static void shader_null_set_params(void *data, unsigned width, unsigned height,
|
||||
unsigned frame_count,
|
||||
const void *info,
|
||||
const void *prev_info,
|
||||
const void *feedback_info,
|
||||
const void *fbo_info, unsigned fbo_info_cnt)
|
||||
{
|
||||
}
|
||||
@ -118,6 +119,12 @@ static bool shader_null_mipmap_input(unsigned idx)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool shader_null_get_feedback_pass(unsigned *idx)
|
||||
{
|
||||
(void)idx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct video_shader *shader_null_get_current_shader(void)
|
||||
{
|
||||
return NULL;
|
||||
@ -135,6 +142,7 @@ const shader_backend_t shader_null_backend = {
|
||||
shader_null_set_coords,
|
||||
shader_null_set_mvp,
|
||||
shader_null_get_prev_textures,
|
||||
shader_null_get_feedback_pass,
|
||||
shader_null_mipmap_input,
|
||||
shader_null_get_current_shader,
|
||||
|
||||
|
@ -35,6 +35,7 @@ typedef struct shader_backend
|
||||
unsigned frame_counter,
|
||||
const void *info,
|
||||
const void *prev_info,
|
||||
const void *feedback_info,
|
||||
const void *fbo_info, unsigned fbo_info_cnt);
|
||||
|
||||
void (*use)(void *data, unsigned index);
|
||||
@ -45,6 +46,7 @@ typedef struct shader_backend
|
||||
bool (*set_coords)(const void *data);
|
||||
bool (*set_mvp)(void *data, const math_matrix_4x4 *mat);
|
||||
unsigned (*get_prev_textures)(void);
|
||||
bool (*get_feedback_pass)(unsigned *pass);
|
||||
bool (*mipmap_input)(unsigned index);
|
||||
|
||||
struct video_shader *(*get_current_shader)(void);
|
||||
|
@ -616,6 +616,9 @@ bool video_shader_read_conf_cgp(config_file_t *conf, struct video_shader *shader
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!config_get_int(conf, "feedback_pass", &shader->feedback_pass))
|
||||
shader->feedback_pass = -1;
|
||||
|
||||
shader->passes = min(shaders, GFX_MAX_SHADERS);
|
||||
for (i = 0; i < shader->passes; i++)
|
||||
{
|
||||
@ -771,6 +774,8 @@ void video_shader_write_conf_cgp(config_file_t *conf,
|
||||
unsigned i;
|
||||
|
||||
config_set_int(conf, "shaders", shader->passes);
|
||||
if (shader->feedback_pass >= 0)
|
||||
config_set_int(conf, "feedback_pass", shader->feedback_pass);
|
||||
|
||||
for (i = 0; i < shader->passes; i++)
|
||||
{
|
||||
|
@ -150,6 +150,10 @@ struct video_shader
|
||||
char script_path[PATH_MAX_LENGTH];
|
||||
char *script; /* Dynamically allocated. Must be free'd. Only used by XML. */
|
||||
char script_class[512];
|
||||
|
||||
/* If < 0, no feedback pass is used. Otherwise,
|
||||
* the FBO after pass #N is passed a texture to next frame. */
|
||||
int feedback_pass;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -246,6 +246,7 @@ def translate_varying(cg):
|
||||
'IN.vertex_coord': 'VertexCoord',
|
||||
'IN.lut_tex_coord': 'LUTTexCoord',
|
||||
'ORIG.tex_coord': 'OrigTexCoord',
|
||||
'FEEDBACK.tex_coord': 'FeedbackTexCoord',
|
||||
'PREV.tex_coord': 'PrevTexCoord',
|
||||
'PREV1.tex_coord': 'Prev1TexCoord',
|
||||
'PREV2.tex_coord': 'Prev2TexCoord',
|
||||
@ -276,6 +277,7 @@ def translate_varying(cg):
|
||||
def translate_texture_size(cg):
|
||||
translations = {
|
||||
'ORIG.texture_size': 'OrigTextureSize',
|
||||
'FEEDBACK.texture_size': 'FeedbackTextureSize',
|
||||
'PREV.texture_size': 'PrevTextureSize',
|
||||
'PREV1.texture_size': 'Prev1TextureSize',
|
||||
'PREV2.texture_size': 'Prev2TextureSize',
|
||||
@ -299,6 +301,7 @@ def translate_texture_size(cg):
|
||||
'PASSPREV7.texture_size': 'PassPrev7TextureSize',
|
||||
'PASSPREV8.texture_size': 'PassPrev8TextureSize',
|
||||
'ORIG.video_size': 'OrigInputSize',
|
||||
'FEEDBACK.video_size': 'FeedbackInputSize',
|
||||
'PREV.video_size': 'PrevInputSize',
|
||||
'PREV1.video_size': 'Prev1InputSize',
|
||||
'PREV2.video_size': 'Prev2InputSize',
|
||||
@ -451,6 +454,7 @@ def replace_global_fragment(source):
|
||||
def translate_texture(cg):
|
||||
translations = {
|
||||
'ORIG.texture': 'OrigTexture',
|
||||
'FEEDBACK.texture': 'FeedbackTexture',
|
||||
'PREV.texture': 'PrevTexture',
|
||||
'PREV1.texture': 'Prev1Texture',
|
||||
'PREV2.texture': 'Prev2Texture',
|
||||
|
Loading…
Reference in New Issue
Block a user