GPU compositing:
authorAntony Riakiotakis <kalast@gmail.com>
Sun, 20 Mar 2016 23:53:48 +0000 (00:53 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 21 Mar 2016 21:43:03 +0000 (22:43 +0100)
Minor optimization: Store the uniform interface of shaders instead of
re-querying every frame.

source/blender/gpu/GPU_compositing.h
source/blender/gpu/GPU_shader.h
source/blender/gpu/intern/gpu_compositing.c
source/blender/gpu/intern/gpu_shader.c

index 892fe4f325538ad78e0d190f65c97ea3997a3405..d506d91a9aac0e4f83090fee8f96619c3351ee14 100644 (file)
@@ -44,6 +44,7 @@ struct GPUOffScreen;
 struct GPUFXSettings;
 struct rcti;
 struct Scene;
+struct GPUShader;
 enum eGPUFXFlags;
 
 /**** Public API *****/
@@ -94,6 +95,10 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
 
 void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
 void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
+
+
+/* initialize and cache the shader unform interface for effects */
+void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect);
 #ifdef __cplusplus
 }
 #endif
index 0317976f9d0046144112ef80793cd89144155313..4c674b460aad9e8669afc568572c0ba271df24ac 100644 (file)
@@ -69,6 +69,8 @@ void GPU_shader_free(GPUShader *shader);
 void GPU_shader_bind(GPUShader *shader);
 void GPU_shader_unbind(void);
 
+void *GPU_shader_get_interface(GPUShader *shader);
+void GPU_shader_set_interface(GPUShader *shader, void *interface);
 int GPU_shader_get_uniform(GPUShader *shader, const char *name);
 void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
        int arraysize, const float *value);
index 8516a2d2882c764b51ebe9176da9c0529c66ac5a..c22f3ed7ed8502d4c7b13f49ce44aca5353ccfa6 100644 (file)
 static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
 static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
 
+
+/* shader interfaces (legacy GL 2 style, without uniform buffer objects) */
+
+typedef struct
+{
+       int ssao_uniform;
+       int ssao_color_uniform;
+       int color_uniform;
+       int depth_uniform;
+       int viewvecs_uniform;
+       int ssao_sample_params_uniform;
+       int ssao_concentric_tex;
+       int ssao_jitter_uniform;
+} GPUSSAOShaderInterface;
+
+typedef struct
+{
+       int invrendertargetdim_uniform;
+       int color_uniform;
+       int dof_uniform;
+       int depth_uniform;
+       int viewvecs_uniform;
+} GPUDOFHQPassOneInterface;
+
+typedef struct
+{
+       int rendertargetdim_uniform;
+       int color_uniform;
+       int coc_uniform;
+       int select_uniform;
+       int dof_uniform;
+} GPUDOFHQPassTwoInterface;
+
+typedef struct
+{
+       int dof_uniform;
+       int invrendertargetdim_uniform;
+       int color_uniform;
+       int far_uniform;
+       int near_uniform;
+       int viewvecs_uniform;
+       int depth_uniform;
+} GPUDOFHQPassThreeInterface;
+
+typedef struct
+{
+       int dof_uniform;
+       int invrendertargetdim_uniform;
+       int color_uniform;
+       int depth_uniform;
+       int viewvecs_uniform;
+} GPUDOFPassOneInterface;
+
+typedef struct
+{
+       int dof_uniform;
+       int invrendertargetdim_uniform;
+       int color_uniform;
+       int depth_uniform;
+       int viewvecs_uniform;
+} GPUDOFPassTwoInterface;
+
+typedef struct
+{
+       int near_coc_downsampled;
+       int near_coc_blurred;
+} GPUDOFPassThreeInterface;
+
+typedef struct
+{
+       int near_coc_downsampled;
+       int invrendertargetdim_uniform;
+} GPUDOFPassFourInterface;
+
+typedef struct
+{
+       int medium_blurred_uniform;
+       int high_blurred_uniform;
+       int dof_uniform;
+       int invrendertargetdim_uniform;
+       int original_uniform;
+       int depth_uniform;
+       int viewvecs_uniform;
+} GPUDOFPassFiveInterface;
+
+typedef struct
+{
+       int depth_uniform;
+} GPUDepthResolveInterface;
+
+
 struct GPUFX {
        /* we borrow the term gbuffer from deferred rendering however this is just a regular
         * depth/color framebuffer. Could be extended later though */
@@ -618,15 +709,13 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
        depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
 
        if (depth_resolve_shader) {
-               int depth_uniform;
-
-               depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");
+               GPUDepthResolveInterface *interface = GPU_shader_get_interface(depth_resolve_shader);
 
                GPU_shader_bind(depth_resolve_shader);
 
                GPU_texture_bind(fx->depth_buffer_xray, 0);
                GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
-               GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);
+               GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
 
                /* draw */
                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -724,9 +813,6 @@ bool GPU_fx_do_composite_pass(
                ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
                if (ssao_shader) {
                        const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
-                       int color_uniform, depth_uniform;
-                       int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
-                       int ssao_jitter_uniform, ssao_concentric_tex;
                        float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
                        float sample_params[3];
 
@@ -737,34 +823,27 @@ bool GPU_fx_do_composite_pass(
 
                        ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
 
-                       ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
-                       ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
-                       color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
-                       depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
-                       viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
-                       ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
-                       ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
-                       ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
+                       GPUSSAOShaderInterface *interface = GPU_shader_get_interface(ssao_shader);
 
                        GPU_shader_bind(ssao_shader);
 
-                       GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
-                       GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
-                       GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
-                       GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 3, 1, sample_params);
+                       GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
+                       GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
+                       GPU_shader_uniform_vector(ssao_shader, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
+                       GPU_shader_uniform_vector(ssao_shader, interface->ssao_sample_params_uniform, 3, 1, sample_params);
 
                        GPU_texture_bind(src, numslots++);
-                       GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
+                       GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
 
                        GPU_texture_bind(fx->depth_buffer, numslots++);
                        GPU_texture_filter_mode(fx->depth_buffer, false, true);
-                       GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
+                       GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
 
                        GPU_texture_bind(fx->jitter_buffer, numslots++);
-                       GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
+                       GPU_shader_uniform_texture(ssao_shader, interface->ssao_jitter_uniform, fx->jitter_buffer);
 
                        GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
-                       GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex);
+                       GPU_shader_uniform_texture(ssao_shader, interface->ssao_concentric_tex, fx->ssao_spiral_samples_tex);
 
                        /* draw */
                        gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
@@ -835,35 +914,26 @@ bool GPU_fx_do_composite_pass(
 
                        /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
                        {
-                               int depth_uniform, dof_uniform;
-                               int viewvecs_uniform;
-                               int invrendertargetdim_uniform, color_uniform;
-
                                float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
 
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
-                               color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
-                               depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
-                               viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+                               GPUDOFHQPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
 
                                GPU_shader_bind(dof_shader_pass1);
 
-                               GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
-                               GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
 
-                               GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
 
                                GPU_texture_bind(fx->depth_buffer, numslots++);
                                GPU_texture_filter_mode(fx->depth_buffer, false, false);
-                               GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
 
                                GPU_texture_bind(src, numslots++);
                                /* disable filtering for the texture so custom downsample can do the right thing */
                                GPU_texture_filter_mode(src, false, false);
-                               GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
 
                                /* target is the downsampled coc buffer */
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
@@ -892,29 +962,23 @@ bool GPU_fx_do_composite_pass(
                        /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
                         * to circle of confusion */
                        {
-                               int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform;
                                int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
                                float selection[2] = {0.0f, 1.0f};
 
-                               rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim");
-
-                               color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
-                               coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer");
-                               select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection");
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+                               GPUDOFHQPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
 
                                GPU_shader_bind(dof_shader_pass2);
 
-                               GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
-                               GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
 
                                GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass2, coc_uniform, fx->dof_nearfar_coc);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
 
                                GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
                                GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_far);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
                                GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
 
                                /* target is the downsampled coc buffer */
@@ -934,13 +998,13 @@ bool GPU_fx_do_composite_pass(
                                GPU_texture_unbind(fx->dof_half_downsampled_far);
                                GPU_framebuffer_texture_detach(fx->dof_far_blur);
 
-                               GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
                                GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
 
                                selection[0] = 1.0f;
                                selection[1] = 0.0f;
 
-                               GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
 
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
                                /* have to clear the buffer unfortunately */
@@ -962,40 +1026,31 @@ bool GPU_fx_do_composite_pass(
 
                        /* third pass, accumulate the near/far blur fields */
                        {
-                               int invrendertargetdim_uniform, near_uniform, color_uniform;
-                               int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform;
-
                                float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
 
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim");
-                               color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
-                               far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer");
-                               near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer");
-                               viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass3, "viewvecs");
-                               depth_uniform = GPU_shader_get_uniform(dof_shader_pass3, "depthbuffer");
+                               GPUDOFHQPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
 
                                GPU_shader_bind(dof_shader_pass3);
 
-                               GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
 
-                               GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]);
+                               GPU_shader_uniform_vector(dof_shader_pass3, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass3, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
 
                                GPU_texture_bind(fx->dof_near_blur, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
                                GPU_texture_filter_mode(fx->dof_near_blur, false, true);
 
                                GPU_texture_bind(fx->dof_far_blur, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
                                GPU_texture_filter_mode(fx->dof_far_blur, false, true);
 
                                GPU_texture_bind(fx->depth_buffer, numslots++);
                                GPU_texture_filter_mode(fx->depth_buffer, false, false);
-                               GPU_shader_uniform_texture(dof_shader_pass3, depth_uniform, fx->depth_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
 
                                GPU_texture_bind(src, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->color_uniform, src);
 
                                /* if this is the last pass, prepare for rendering on the frambuffer */
                                gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
@@ -1052,29 +1107,22 @@ bool GPU_fx_do_composite_pass(
 
                        /* pass first, first level of blur in low res buffer */
                        {
-                               int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
-                               int viewvecs_uniform;
-
                                float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
 
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
-                               color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
-                               depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
-                               viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+                               GPUDOFPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
 
                                GPU_shader_bind(dof_shader_pass1);
 
-                               GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
-                               GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
 
                                GPU_texture_bind(src, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
+                               GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
 
                                GPU_texture_bind(fx->depth_buffer, numslots++);
                                GPU_texture_filter_mode(fx->depth_buffer, false, true);
-                               GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
 
                                /* target is the downsampled coc buffer */
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
@@ -1093,34 +1141,28 @@ bool GPU_fx_do_composite_pass(
 
                        /* second pass, gaussian blur the downsampled image */
                        {
-                               int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
-                               int viewvecs_uniform;
                                float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
                                                               1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
                                float tmp = invrendertargetdim[0];
                                invrendertargetdim[0] = 0.0f;
 
-                               dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
+                               GPUDOFPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
 
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
-                               color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
-                               depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
-                               viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
+                               dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
 
                                /* Blurring vertically */
                                GPU_shader_bind(dof_shader_pass2);
 
-                               GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
-                               GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
 
                                GPU_texture_bind(fx->depth_buffer, numslots++);
                                GPU_texture_filter_mode(fx->depth_buffer, false, true);
-                               GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
 
                                GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
 
                                /* use final buffer as a temp here */
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
@@ -1135,10 +1177,10 @@ bool GPU_fx_do_composite_pass(
                                /* Blurring horizontally */
                                invrendertargetdim[0] = tmp;
                                invrendertargetdim[1] = 0.0f;
-                               GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
 
                                GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
 
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
                                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -1157,18 +1199,15 @@ bool GPU_fx_do_composite_pass(
 
                        /* third pass, calculate near coc */
                        {
-                               int near_coc_downsampled, near_coc_blurred;
-
-                               near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
-                               near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
+                               GPUDOFPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
 
                                GPU_shader_bind(dof_shader_pass3);
 
                                GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
 
                                GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
 
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
 
@@ -1185,19 +1224,16 @@ bool GPU_fx_do_composite_pass(
 
                        /* fourth pass blur final coc once to eliminate discontinuities */
                        {
-                               int near_coc_downsampled;
-                               int invrendertargetdim_uniform;
                                float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
                                                               1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
 
-                               near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
+                               GPUDOFPassFourInterface *interface = GPU_shader_get_interface(dof_shader_pass4);
 
                                GPU_shader_bind(dof_shader_pass4);
 
                                GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
-                               GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
+                               GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
 
                                GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
 
@@ -1214,36 +1250,28 @@ bool GPU_fx_do_composite_pass(
 
                        /* final pass, merge blurred layers according to final calculated coc */
                        {
-                               int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
-                               int invrendertargetdim_uniform, viewvecs_uniform;
                                float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
 
-                               medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
-                               high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
-                               dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
-                               invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
-                               original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
-                               depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
-                               viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
+                               GPUDOFPassFiveInterface *interface = GPU_shader_get_interface(dof_shader_pass5);
 
                                GPU_shader_bind(dof_shader_pass5);
 
-                               GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
-                               GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-                               GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
+                               GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
+                               GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+                               GPU_shader_uniform_vector(dof_shader_pass5, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
 
                                GPU_texture_bind(src, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
+                               GPU_shader_uniform_texture(dof_shader_pass5, interface->original_uniform, src);
 
                                GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass5, interface->high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
 
                                GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
-                               GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
 
                                GPU_texture_bind(fx->depth_buffer, numslots++);
                                GPU_texture_filter_mode(fx->depth_buffer, false, true);
-                               GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
+                               GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
 
                                /* if this is the last pass, prepare for rendering on the frambuffer */
                                gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
@@ -1298,3 +1326,149 @@ void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
        fx_ssao->attenuation = 1.0f;
        fx_ssao->samples = 20;
 }
+
+void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect)
+{
+       if (!shader)
+               return;
+
+       switch (effect)
+       {
+               case GPU_SHADER_FX_SSAO:
+               {
+                       GPUSSAOShaderInterface *interface = MEM_mallocN(sizeof(GPUSSAOShaderInterface), "GPUSSAOShaderInterface");
+
+                       interface->ssao_uniform = GPU_shader_get_uniform(shader, "ssao_params");
+                       interface->ssao_color_uniform = GPU_shader_get_uniform(shader, "ssao_color");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+                       interface->ssao_sample_params_uniform = GPU_shader_get_uniform(shader, "ssao_sample_params");
+                       interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
+                       interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
+               {
+                       GPUDOFHQPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassOneInterface), "GPUDOFHQPassOneInterface");
+
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
+               {
+                       GPUDOFHQPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassTwoInterface), "GPUDOFHQPassTwoInterface");
+
+                       interface->rendertargetdim_uniform = GPU_shader_get_uniform(shader, "rendertargetdim");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->coc_uniform = GPU_shader_get_uniform(shader, "cocbuffer");
+                       interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
+               {
+                       GPUDOFHQPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassThreeInterface), "GPUDOFHQPassThreeInterface");
+
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->far_uniform = GPU_shader_get_uniform(shader, "farbuffer");
+                       interface->near_uniform = GPU_shader_get_uniform(shader, "nearbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+               {
+                       GPUDOFPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFPassOneInterface), "GPUDOFPassOneInterface");
+
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+               {
+                       GPUDOFPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFPassTwoInterface), "GPUDOFPassTwoInterface");
+
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+                       interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+               {
+                       GPUDOFPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFPassThreeInterface), "GPUDOFPassThreeInterface");
+
+                       interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+               {
+                       GPUDOFPassFourInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFourInterface), "GPUDOFPassFourInterface");
+
+                       interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+               case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+               {
+                       GPUDOFPassFiveInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFiveInterface), "GPUDOFPassFiveInterface");
+
+                       interface->medium_blurred_uniform = GPU_shader_get_uniform(shader, "mblurredcolorbuffer");
+                       interface->high_blurred_uniform = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
+                       interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
+                       interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
+                       interface->original_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+                       interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               case GPU_SHADER_FX_DEPTH_RESOLVE:
+               {
+                       GPUDepthResolveInterface *interface = MEM_mallocN(sizeof(GPUDepthResolveInterface), "GPUDepthResolveInterface");
+
+                       interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
+
+                       GPU_shader_set_interface(shader, interface);
+                       break;
+               }
+
+               default:
+                       break;
+       }
+}
+
index f0bab2bb983ead27ed33f41a09c1c8bcdecdb418..49f244083f99b60397e2d8a87176877b64ba8d12 100644 (file)
@@ -84,6 +84,8 @@ struct GPUShader {
 
        int totattrib;   /* total number of attributes */
        int uniforms;    /* required uniforms */
+
+       void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
 };
 
 static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
@@ -464,6 +466,10 @@ void GPU_shader_free(GPUShader *shader)
                glDeleteShader(shader->fragment);
        if (shader->program)
                glDeleteProgram(shader->program);
+
+       if (shader->uniform_interface)
+               MEM_freeN(shader->uniform_interface);
+
        MEM_freeN(shader);
 }
 
@@ -472,6 +478,16 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
        return glGetUniformLocation(shader->program, name);
 }
 
+void *GPU_shader_get_interface(GPUShader *shader)
+{
+       return shader->uniform_interface;
+}
+
+void GPU_shader_set_interface(GPUShader *shader, void *interface)
+{
+       shader->uniform_interface = interface;
+}
+
 void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
 {
        if (location == -1 || value == NULL)
@@ -609,15 +625,15 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
 
 #define MAX_DEFINES 100
 
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
 {
        int offset;
        char defines[MAX_DEFINES] = "";
        /* avoid shaders out of range */
-       if (effects >= MAX_FX_SHADERS)
+       if (effect >= MAX_FX_SHADERS)
                return NULL;
 
-       offset = 2 * effects;
+       offset = 2 * effect;
 
        if (persp) {
                offset += 1;
@@ -625,59 +641,61 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
        }
 
        if (!GG.shaders.fx_shaders[offset]) {
-               GPUShader *shader;
+               GPUShader *shader = NULL;
 
-               switch (effects) {
+               switch (effect) {
                        case GPU_SHADER_FX_SSAO:
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
                                strcat(defines, "#define FIRST_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
                                strcat(defines, "#define SECOND_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
                                strcat(defines, "#define THIRD_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
                                strcat(defines, "#define FOURTH_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
                                strcat(defines, "#define FIFTH_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
                                strcat(defines, "#define FIRST_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
                                strcat(defines, "#define SECOND_PASS\n");
                                shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
                                                           defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
-                               GG.shaders.fx_shaders[offset] = shader;
                                break;
 
                        case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
                                strcat(defines, "#define THIRD_PASS\n");
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
                                break;
 
                        case GPU_SHADER_FX_DEPTH_RESOLVE:
-                               GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+                               shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
                                break;
                }
+
+               GG.shaders.fx_shaders[offset] = shader;
+               GPU_fx_shader_init_interface(shader, effect);
        }
 
        return GG.shaders.fx_shaders[offset];
@@ -708,7 +726,7 @@ void GPU_shader_free_builtin_shaders(void)
                GG.shaders.smoke_fire = NULL;
        }
 
-       for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+       for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
                if (GG.shaders.fx_shaders[i]) {
                        GPU_shader_free(GG.shaders.fx_shaders[i]);
                        GG.shaders.fx_shaders[i] = NULL;