From 3b9957afac0555a126d1941d7027fb52e29b309a Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 22 Nov 2017 19:47:31 +0100 Subject: [PATCH] Support other output formats than GL_RGBA16F; was easier than originally feared. --- compute_shader_test.cpp | 18 ++++++++++++++++++ effect_chain.cpp | 26 ++++++++++++-------------- effect_chain.h | 8 ++++---- header.comp | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/compute_shader_test.cpp b/compute_shader_test.cpp index 5a74f40..50b2694 100644 --- a/compute_shader_test.cpp +++ b/compute_shader_test.cpp @@ -65,4 +65,22 @@ TEST(ComputeShaderTest, LastEffectInChain) { expect_equal(data, out_data, 3, 2); } +TEST(ComputeShaderTest, Render8BitTo8Bit) { + uint8_t data[] = { + 14, 200, 80, + 90, 100, 110, + }; + uint8_t out_data[6]; + EffectChainTester tester(nullptr, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, GL_RGBA8); + if (!movit_compute_shaders_supported) { + fprintf(stderr, "Skipping test; no support for compile shaders.\n"); + return; + } + tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 3, 2); + tester.get_chain()->add_effect(new IdentityAlphaComputeEffect()); + tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR); + + expect_equal(data, out_data, 3, 2); +} + } // namespace movit diff --git a/effect_chain.cpp b/effect_chain.cpp index 091bda8..d56a248 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -1950,11 +1950,11 @@ void EffectChain::render(GLuint dest_fbo, const vector &dest // Find a texture for this phase. inform_input_sizes(phase); find_output_size(phase); - GLuint tex_num = 0; + vector phase_destinations; if (!last_phase) { - tex_num = resource_pool->create_2d_texture(intermediate_format, phase->output_width, phase->output_height); - assert(tex_num != 0); + GLuint tex_num = resource_pool->create_2d_texture(intermediate_format, phase->output_width, phase->output_height); output_textures.insert(make_pair(phase, tex_num)); + phase_destinations.push_back(DestinationTexture{ tex_num, intermediate_format }); // The output texture needs to have valid state to be written to by a compute shader. glActiveTexture(GL_TEXTURE0); @@ -1964,14 +1964,11 @@ void EffectChain::render(GLuint dest_fbo, const vector &dest glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); check_error(); } else if (phase->is_compute_shader) { - // TODO: Support more than one destination. assert(!destinations.empty()); - tex_num = destinations[0].texnum; - assert(destinations[0].format == GL_RGBA16F); - assert(destinations[0].texnum != 0); + phase_destinations = destinations; } - execute_phase(phase, output_textures, tex_num, &generated_mipmaps); + execute_phase(phase, output_textures, phase_destinations, &generated_mipmaps); if (do_phase_timing) { glEndQuery(GL_TIME_ELAPSED); } @@ -2053,7 +2050,7 @@ void EffectChain::print_phase_timing() void EffectChain::execute_phase(Phase *phase, const map &output_textures, - GLuint dest_texture, + const std::vector &destinations, set *generated_mipmaps) { // Set up RTT inputs for this phase. @@ -2080,19 +2077,20 @@ void EffectChain::execute_phase(Phase *phase, // And now the output. GLuint fbo = 0; if (phase->is_compute_shader) { - assert(dest_texture != 0); + assert(!destinations.empty()); // This is currently the only place where we use image units, - // so we can always use 0. + // so we can always start at 0. TODO: Support multiple destinations. phase->outbuf_image_unit = 0; - glBindImageTexture(phase->outbuf_image_unit, dest_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA16F); + glBindImageTexture(phase->outbuf_image_unit, destinations[0].texnum, 0, GL_FALSE, 0, GL_WRITE_ONLY, destinations[0].format); check_error(); phase->inv_output_size.x = 1.0f / phase->output_width; phase->inv_output_size.y = 1.0f / phase->output_height; phase->output_texcoord_adjust.x = 0.5f / phase->output_width; phase->output_texcoord_adjust.y = 0.5f / phase->output_height; - } else if (dest_texture != 0) { - fbo = resource_pool->create_fbo(dest_texture); + } else if (!destinations.empty()) { + assert(destinations.size() == 1); + fbo = resource_pool->create_fbo(destinations[0].texnum); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glViewport(0, 0, phase->output_width, phase->output_height); } diff --git a/effect_chain.h b/effect_chain.h index ee387a9..8d75e8a 100644 --- a/effect_chain.h +++ b/effect_chain.h @@ -394,8 +394,8 @@ public: // except that it is more efficient if the last phase contains a compute shader. // Thus, prefer this to render_to_fbo() where possible. // - // The format must currently be GL_RGBA16F, and only one destination - // texture is supported. Both of these restrictions will be lifted in the future. + // Only one destination texture is supported. This restriction will be lifted + // in the future. // // All destination textures must be exactly of size x . // width and height can not be zero. @@ -481,11 +481,11 @@ private: unsigned x, unsigned y, unsigned width, unsigned height); // Execute one phase, ie. set up all inputs, effects and outputs, and render the quad. - // If dest_texture is 0, uses whatever output is current (and the phase must not be + // If is empty, uses whatever output is current (and the phase must not be // a compute shader). void execute_phase(Phase *phase, const std::map &output_textures, - GLuint dest_texture, + const std::vector &destinations, std::set *generated_mipmaps); // Set up uniforms for one phase. The program must already be bound. diff --git a/header.comp b/header.comp index 2766568..266e24f 100644 --- a/header.comp +++ b/header.comp @@ -3,7 +3,7 @@ #extension GL_ARB_shader_image_load_store : enable // FIXME this needs to be auto-output or something -layout(rgba16f) uniform restrict writeonly image2D outbuf; +uniform restrict writeonly image2D outbuf; vec4 tex2D(sampler2D s, vec2 coord) { -- 2.39.2