std::shared_ptr<SpectraCalculator> SpectraGetDefaultGPUFourierTransf( SpectraSharedObjects& shared_objects, std::size_t spectrum_size) { std::size_t frame_size = spectrum_size * 2 - 1; shared_objects.GLCanvas()->SetCurrent(*shared_objects.GLContext()); assert(spectrum_size > 2); return std::make_shared<SpectraDefaultGPUMatrixTransf>( shared_objects, frame_size, spectrum_size, "Discrete Complex Fourier Transform (GPU)", SpectraFourierMatrixGen(frame_size, spectrum_size)); }
SpectraDefaultGPUMatrixTransf::SpectraDefaultGPUMatrixTransf( SpectraSharedObjects& shared_objects, std::size_t in_sz, std::size_t out_sz, const std::string& transf_name, const std::function< std::complex<double>( std::size_t, std::size_t, std::size_t, std::size_t ) >& gen ): gl_context(shared_objects.GLContext()) , gl_canvas(shared_objects.GLCanvas()) , max_transforms(4) , current_transform(0) , in_size(in_sz) , out_size(out_sz) , name(transf_name) , transf_prog(shared_objects.BuildProgramWithXFB("xfb_matrix_transf.prog", "Output")) , prog_input_offs(transf_prog, "InputOffs") , prog_input_size(transf_prog, "InputSize") , prog_input_data(transf_prog, "InputData") , prog_matrix_data(transf_prog, "MatrixData") , output_bufs(max_transforms) , xfbs(max_transforms) , queries(max_transforms) { assert(gl_context); assert(gl_canvas); std::vector<GLfloat> mat_data(in_size*out_size*2); auto m = mat_data.begin(); for(std::size_t row=0; row!=out_size; ++row) { for(std::size_t col=0; col!=in_size; ++col) { std::complex<double> v = gen(col, row, in_size, out_size); *m = GLfloat(v.real()); ++m; *m = GLfloat(v.imag()); ++m; } } assert(m == mat_data.end()); using namespace oglplus; matrix_buf.Bind(Buffer::Target::Texture); Buffer::Data(Buffer::Target::Texture, mat_data); Texture::Active(0); matrix_tex.Bind(Texture::Target::Buffer); Texture::Buffer( Texture::Target::Buffer, PixelDataInternalFormat::RG32F, matrix_buf ); std::vector<GLfloat> init_data(in_size*max_transforms, 0.0f); input_buf.Bind(Buffer::Target::Texture); Buffer::Data(Buffer::Target::Texture, init_data); Texture::Active(1); input_tex.Bind(Texture::Target::Buffer); Texture::Buffer( Texture::Target::Buffer, PixelDataInternalFormat::R32F, input_buf ); init_data.resize(out_size, 0.0f); vao.Bind(); init_buf.Bind(Buffer::Target::Array); Buffer::Data(Buffer::Target::Array, init_data); (transf_prog|"Initial").Setup<GLfloat>().Enable(); VertexArray::Unbind(); for(GLuint t=0; t!=max_transforms; ++t) { xfbs[t].Bind(); output_bufs[t].Bind(Buffer::Target::TransformFeedback); Buffer::Data( Buffer::Target::TransformFeedback, init_data, Buffer::Property::Usage::DynamicCopy ); output_bufs[t].BindBase( Buffer::IndexedTarget::TransformFeedback, 0 ); } }