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
// Find a texture for this phase.
inform_input_sizes(phase);
find_output_size(phase);
- GLuint tex_num = 0;
+ vector<DestinationTexture> 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);
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);
}
void EffectChain::execute_phase(Phase *phase,
const map<Phase *, GLuint> &output_textures,
- GLuint dest_texture,
+ const std::vector<DestinationTexture> &destinations,
set<Phase *> *generated_mipmaps)
{
// Set up RTT inputs for this 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);
}
// 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 <width> x <height>.
// width and height can not be zero.
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 <destinations> is empty, uses whatever output is current (and the phase must not be
// a compute shader).
void execute_phase(Phase *phase,
const std::map<Phase *, GLuint> &output_textures,
- GLuint dest_texture,
+ const std::vector<DestinationTexture> &destinations,
std::set<Phase *> *generated_mipmaps);
// Set up uniforms for one phase. The program must already be bound.