From: Steinar H. Gunderson Date: Sat, 25 Nov 2017 10:26:54 +0000 (+0100) Subject: Support top-left origin for compute shaders. X-Git-Tag: 1.6.0~29 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=a48d62d61ada1226caaa9fd42846672cfe0249e8 Support top-left origin for compute shaders. --- diff --git a/effect_chain.cpp b/effect_chain.cpp index a4d9c86..b821023 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -555,20 +555,31 @@ void EffectChain::compile_glsl_program(Phase *phase) extract_uniform_declarations(effect->uniforms_mat3, "mat3", effect_id, &phase->uniforms_mat3, &frag_shader_uniforms); } - frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader; - string vert_shader = read_version_dependent_file("vs", "vert"); // If we're the last phase and need to flip the picture to compensate for - // the origin, tell the vertex shader so. - if (phase->output_node->outgoing_links.empty() && output_origin == OUTPUT_ORIGIN_TOP_LEFT) { - const string needle = "#define FLIP_ORIGIN 0"; - size_t pos = vert_shader.find(needle); - assert(pos != string::npos); + // the origin, tell the vertex or compute shader so. + bool is_last_phase; + if (has_dummy_effect) { + is_last_phase = (phase->output_node->outgoing_links.size() == 1 && + phase->output_node->outgoing_links[0]->effect->effect_type_id() == "ComputeShaderOutputDisplayEffect"); + } else { + is_last_phase = phase->output_node->outgoing_links.empty(); + } + if (is_last_phase && output_origin == OUTPUT_ORIGIN_TOP_LEFT) { + if (phase->is_compute_shader) { + frag_shader_header += "#define FLIP_ORIGIN 1\n"; + } else { + const string needle = "#define FLIP_ORIGIN 0"; + size_t pos = vert_shader.find(needle); + assert(pos != string::npos); - vert_shader[pos + needle.size() - 1] = '1'; + vert_shader[pos + needle.size() - 1] = '1'; + } } + frag_shader = frag_shader_header + frag_shader_uniforms + frag_shader; + if (phase->is_compute_shader) { phase->glsl_program_num = resource_pool->compile_glsl_compute_program(frag_shader); diff --git a/effect_chain_test.cpp b/effect_chain_test.cpp index 324ddae..31e8a5d 100644 --- a/effect_chain_test.cpp +++ b/effect_chain_test.cpp @@ -99,7 +99,22 @@ TEST(MirrorTest, BasicTest) { expect_equal(expected_data, out_data, 3, 2); } -TEST(EffectChainTest, TopLeftOrigin) { +class WithAndWithoutComputeShaderTest : public testing::TestWithParam { +}; +INSTANTIATE_TEST_CASE_P(WithAndWithoutComputeShaderTest, + WithAndWithoutComputeShaderTest, + testing::Values("fragment", "compute")); + +// An effect that does nothing, but as a compute shader. +class IdentityComputeEffect : public Effect { +public: + IdentityComputeEffect() {} + virtual string effect_type_id() const { return "IdentityComputeEffect"; } + virtual bool is_compute_shader() const { return true; } + string output_fragment_shader() { return read_file("identity.comp"); } +}; + +TEST_P(WithAndWithoutComputeShaderTest, TopLeftOrigin) { float data[] = { 0.0f, 0.25f, 0.3f, 0.75f, 1.0f, 1.0f, @@ -113,6 +128,9 @@ TEST(EffectChainTest, TopLeftOrigin) { float out_data[6]; EffectChainTester tester(data, 3, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR); tester.get_chain()->set_output_origin(OUTPUT_ORIGIN_TOP_LEFT); + if (GetParam() == "compute") { + tester.get_chain()->add_effect(new IdentityComputeEffect()); + } tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR); expect_equal(expected_data, out_data, 3, 2); @@ -1113,21 +1131,6 @@ public: bool sets_virtual_output_size() const override { return false; } }; -class WithAndWithoutComputeShaderTest : public testing::TestWithParam { -}; -INSTANTIATE_TEST_CASE_P(WithAndWithoutComputeShaderTest, - WithAndWithoutComputeShaderTest, - testing::Values("fragment", "compute")); - -// An effect that does nothing, but as a compute shader. -class IdentityComputeEffect : public Effect { -public: - IdentityComputeEffect() {} - virtual string effect_type_id() const { return "IdentityComputeEffect"; } - virtual bool is_compute_shader() const { return true; } - string output_fragment_shader() { return read_file("identity.comp"); } -}; - // An effect that promises one-to-one sampling (unlike IdentityEffect). class OneToOneEffect : public Effect { public: diff --git a/footer.comp b/footer.comp index a28014d..c4d1305 100644 --- a/footer.comp +++ b/footer.comp @@ -5,6 +5,10 @@ #define SQUARE_ROOT_TRANSFORMATION 0 #endif +#ifndef FLIP_ORIGIN +#define FLIP_ORIGIN 0 +#endif + void main() { INPUT(); @@ -30,5 +34,10 @@ void cs_output(ivec2 coord, vec4 val) // Make sure we don't give negative values to sqrt. val.rgb = sqrt(max(val.rgb, 0.0)); #endif + +#if FLIP_ORIGIN + coord.y = imageSize(outbuf).y - coord.y - 1; +#endif + imageStore(outbuf, coord, val); } diff --git a/header.comp b/header.comp index 3c07007..dc2fd08 100644 --- a/header.comp +++ b/header.comp @@ -1,6 +1,7 @@ #version 150 #extension GL_ARB_compute_shader : enable #extension GL_ARB_shader_image_load_store : enable +#extension GL_ARB_shader_image_size : enable // FIXME this needs to be auto-output or something uniform restrict writeonly image2D outbuf; diff --git a/init.cpp b/init.cpp index ce2ce50..5e6c642 100644 --- a/init.cpp +++ b/init.cpp @@ -318,7 +318,8 @@ bool check_extensions() (epoxy_is_desktop_gl() && (epoxy_gl_version() >= 43 || (epoxy_has_gl_extension("GL_ARB_compute_shader") && - epoxy_has_gl_extension("GL_ARB_shader_image_load_store")))); + epoxy_has_gl_extension("GL_ARB_shader_image_load_store") && + epoxy_has_gl_extension("GL_ARB_shader_image_size")))); return true; }