/* Assignment operator overloading. We signal to * the references counter that we release the * previous address and hold the new one */ SmartPointer<T>& operator=(SmartPointer<T> sp) { unuse(); pointer = sp.pointer; use(); return *this; }
Program::~Program() { if (m_Id == m_usedProgramId) { //if this program is used take care of "unusing" unuse(); } //detach shaders detachAllShaders(); //finally delete glDeleteProgram(m_Id); }
void Batch3DGeometry::render_batch() { //Vertices data glBindBuffer(GL_ARRAY_BUFFER, m_vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex3D), vertices.data(), GL_STATIC_DRAW); //Indices data glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_vbo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(U32), indices.data(), GL_STATIC_DRAW); Shader* old_shader = nullptr; U64 buffer_data_offset = 0; for (const auto& rb : m_render_batches){ auto curr_shader = rb.model->material.shader; curr_shader->use(); U32 old_shader_size = 0;//keep track of the size of the last used shader if (old_shader)old_shader_size = old_shader->attributes_struct_size; //If the new batch has a different shader than the one before, //enable attributes and send global data if (old_shader != curr_shader){ old_shader = curr_shader; enable_attributes(curr_shader); U8 curr_samp = 0; //Send global shader uniforms for (const auto& cnt : curr_shader->global_uniforms_data){ curr_shader->send_global_uniform_to_shader(cnt.first, cnt.second.value, &curr_samp); } } U8 current_sampler = 0; for (const auto& cnt : rb.model->material.uniform_map) { curr_shader->send_material_uniform_to_shader(cnt.first, cnt.second, ¤t_sampler); } glBindBuffer(GL_ARRAY_BUFFER, m_i_vbo); glBufferData(GL_ARRAY_BUFFER, rb.num_instances * curr_shader->attributes_struct_size, (void*)((U64)input_instances + buffer_data_offset ), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); buffer_data_offset += rb.num_instances* curr_shader->attributes_struct_size; U32 offset = rb.indices_offset * sizeof(U32); glDrawElementsInstancedBaseVertex(GL_TRIANGLES, rb.num_indices, GL_UNSIGNED_INT, (void*)offset, rb.num_instances, rb.vertex_offset); curr_shader->unuse(); } }
void Lightmap::render(const Falltergeist::Point &pos) { if (_indexes<=0) return; GL_CHECK(glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR)); auto shader = ResourceManager::getInstance()->shader("lightmap"); GL_CHECK(shader->use()); GL_CHECK(shader->setUniform(_uniformMVP, Game::getInstance()->renderer()->getMVP())); // set camera offset GL_CHECK(shader->setUniform(_uniformOffset, glm::vec2((float)pos.x(), (float)pos.y()) )); GL_CHECK(shader->setUniform(_uniformFade,Game::getInstance()->renderer()->fadeColor())); GL_CHECK(glBindVertexArray(_vao)); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, _coords)); GL_CHECK(glVertexAttribPointer(_attribPos, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 )); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, _lights)); GL_CHECK(glVertexAttribPointer(_attribLights, 1, GL_FLOAT, GL_FALSE, 0, (void*)0 )); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo)); GL_CHECK(glEnableVertexAttribArray(_attribPos)); GL_CHECK(glEnableVertexAttribArray(_attribLights)); GL_CHECK(glDrawElements(GL_TRIANGLES, _indexes, GL_UNSIGNED_INT, 0 )); GL_CHECK(glDisableVertexAttribArray(_attribPos)); GL_CHECK(glDisableVertexAttribArray(_attribLights)); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0)); GL_CHECK(glBindVertexArray(0)); GL_CHECK(shader->unuse()); GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); }
bool StGLStereoFrameBuffer::StGLStereoProgram::link(StGLContext& theCtx) { if(!StGLProgram::link(theCtx)) { return false; } StGLVarLocation uniTexLLoc = StGLProgram::getUniformLocation(theCtx, "texL"); StGLVarLocation uniTexRLoc = StGLProgram::getUniformLocation(theCtx, "texR"); atrVVertexLoc = StGLProgram::getAttribLocation(theCtx, "vVertex"); atrVTexCoordLoc = StGLProgram::getAttribLocation(theCtx, "vTexCoord"); if(uniTexLLoc.isValid() && uniTexRLoc.isValid()) { use(theCtx); theCtx.core20fwd->glUniform1i(uniTexLLoc, StGLProgram::TEXTURE_SAMPLE_0); // GL_TEXTURE0 in multitexture theCtx.core20fwd->glUniform1i(uniTexRLoc, StGLProgram::TEXTURE_SAMPLE_1); // GL_TEXTURE1 in multitexture unuse(theCtx); } return uniTexRLoc.isValid() && uniTexLLoc.isValid() && atrVVertexLoc.isValid() && atrVTexCoordLoc.isValid(); }
/* Signal to the references counter that we * release the current address */ ~SmartPointer() { unuse(); }
/** * Find instruction src's which are mov's that can be collapsed, replacing * the mov dst with the mov src */ static void instr_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr) { struct ir3_register *reg; if (instr->regs_count == 0) return; if (ir3_instr_check_mark(instr)) return; /* walk down the graph from each src: */ foreach_src_n(reg, n, instr) { struct ir3_instruction *src = ssa(reg); if (!src) continue; instr_cp(ctx, src); /* TODO non-indirect access we could figure out which register * we actually want and allow cp.. */ if (reg->flags & IR3_REG_ARRAY) continue; /* Don't CP absneg into meta instructions, that won't end well: */ if (is_meta(instr) && (src->opc != OPC_MOV)) continue; reg_cp(ctx, instr, reg, n); } if (instr->regs[0]->flags & IR3_REG_ARRAY) { struct ir3_instruction *src = ssa(instr->regs[0]); if (src) instr_cp(ctx, src); } if (instr->address) { instr_cp(ctx, instr->address); ir3_instr_set_address(instr, eliminate_output_mov(instr->address)); } /* we can end up with extra cmps.s from frontend, which uses a * * cmps.s p0.x, cond, 0 * * as a way to mov into the predicate register. But frequently 'cond' * is itself a cmps.s/cmps.f/cmps.u. So detect this special case and * just re-write the instruction writing predicate register to get rid * of the double cmps. */ if ((instr->opc == OPC_CMPS_S) && (instr->regs[0]->num == regid(REG_P0, 0)) && ssa(instr->regs[1]) && (instr->regs[2]->flags & IR3_REG_IMMED) && (instr->regs[2]->iim_val == 0)) { struct ir3_instruction *cond = ssa(instr->regs[1]); switch (cond->opc) { case OPC_CMPS_S: case OPC_CMPS_F: case OPC_CMPS_U: instr->opc = cond->opc; instr->flags = cond->flags; instr->cat2 = cond->cat2; instr->address = cond->address; instr->regs[1] = cond->regs[1]; instr->regs[2] = cond->regs[2]; instr->barrier_class |= cond->barrier_class; instr->barrier_conflict |= cond->barrier_conflict; unuse(cond); break; default: break; } } /* Handle converting a sam.s2en (taking samp/tex idx params via * register) into a normal sam (encoding immediate samp/tex idx) * if they are immediate. This saves some instructions and regs * in the common case where we know samp/tex at compile time: */ if (is_tex(instr) && (instr->flags & IR3_INSTR_S2EN) && !(ir3_shader_debug & IR3_DBG_FORCES2EN)) { /* The first src will be a fan-in (collect), if both of it's * two sources are mov from imm, then we can */ struct ir3_instruction *samp_tex = ssa(instr->regs[1]); debug_assert(samp_tex->opc == OPC_META_FI); struct ir3_instruction *samp = ssa(samp_tex->regs[1]); struct ir3_instruction *tex = ssa(samp_tex->regs[2]); if ((samp->opc == OPC_MOV) && (samp->regs[1]->flags & IR3_REG_IMMED) && (tex->opc == OPC_MOV) && (tex->regs[1]->flags & IR3_REG_IMMED)) { instr->flags &= ~IR3_INSTR_S2EN; instr->cat5.samp = samp->regs[1]->iim_val; instr->cat5.tex = tex->regs[1]->iim_val; instr->regs[1]->instr = NULL; } } }
/** * Handle cp for a given src register. This additionally handles * the cases of collapsing immedate/const (which replace the src * register with a non-ssa src) or collapsing mov's from relative * src (which needs to also fixup the address src reference by the * instruction). */ static void reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, struct ir3_register *reg, unsigned n) { struct ir3_instruction *src = ssa(reg); if (is_eligible_mov(src, true)) { /* simple case, no immed/const/relativ, only mov's w/ ssa src: */ struct ir3_register *src_reg = src->regs[1]; unsigned new_flags = reg->flags; combine_flags(&new_flags, src); if (valid_flags(instr, n, new_flags)) { if (new_flags & IR3_REG_ARRAY) { debug_assert(!(reg->flags & IR3_REG_ARRAY)); reg->array = src_reg->array; } reg->flags = new_flags; reg->instr = ssa(src_reg); instr->barrier_class |= src->barrier_class; instr->barrier_conflict |= src->barrier_conflict; unuse(src); reg->instr->use_count++; } } else if (is_same_type_mov(src) && /* cannot collapse const/immed/etc into meta instrs: */ !is_meta(instr)) { /* immed/const/etc cases, which require some special handling: */ struct ir3_register *src_reg = src->regs[1]; unsigned new_flags = reg->flags; combine_flags(&new_flags, src); if (!valid_flags(instr, n, new_flags)) { /* See if lowering an immediate to const would help. */ if (valid_flags(instr, n, (new_flags & ~IR3_REG_IMMED) | IR3_REG_CONST)) { debug_assert(new_flags & IR3_REG_IMMED); instr->regs[n + 1] = lower_immed(ctx, src_reg, new_flags); return; } /* special case for "normal" mad instructions, we can * try swapping the first two args if that fits better. * * the "plain" MAD's (ie. the ones that don't shift first * src prior to multiply) can swap their first two srcs if * src[0] is !CONST and src[1] is CONST: */ if ((n == 1) && is_mad(instr->opc) && !(instr->regs[0 + 1]->flags & (IR3_REG_CONST | IR3_REG_RELATIV)) && valid_flags(instr, 0, new_flags & ~IR3_REG_IMMED)) { /* swap src[0] and src[1]: */ struct ir3_register *tmp; tmp = instr->regs[0 + 1]; instr->regs[0 + 1] = instr->regs[1 + 1]; instr->regs[1 + 1] = tmp; n = 0; } else { return; } } /* Here we handle the special case of mov from * CONST and/or RELATIV. These need to be handled * specially, because in the case of move from CONST * there is no src ir3_instruction so we need to * replace the ir3_register. And in the case of * RELATIV we need to handle the address register * dependency. */ if (src_reg->flags & IR3_REG_CONST) { /* an instruction cannot reference two different * address registers: */ if ((src_reg->flags & IR3_REG_RELATIV) && conflicts(instr->address, reg->instr->address)) return; /* This seems to be a hw bug, or something where the timings * just somehow don't work out. This restriction may only * apply if the first src is also CONST. */ if ((opc_cat(instr->opc) == 3) && (n == 2) && (src_reg->flags & IR3_REG_RELATIV) && (src_reg->array.offset == 0)) return; src_reg = ir3_reg_clone(instr->block->shader, src_reg); src_reg->flags = new_flags; instr->regs[n+1] = src_reg; if (src_reg->flags & IR3_REG_RELATIV) ir3_instr_set_address(instr, reg->instr->address); return; } if ((src_reg->flags & IR3_REG_RELATIV) && !conflicts(instr->address, reg->instr->address)) { src_reg = ir3_reg_clone(instr->block->shader, src_reg); src_reg->flags = new_flags; instr->regs[n+1] = src_reg; ir3_instr_set_address(instr, reg->instr->address); return; } /* NOTE: seems we can only do immed integers, so don't * need to care about float. But we do need to handle * abs/neg *before* checking that the immediate requires * few enough bits to encode: * * TODO: do we need to do something to avoid accidentally * catching a float immed? */ if (src_reg->flags & IR3_REG_IMMED) { int32_t iim_val = src_reg->iim_val; debug_assert((opc_cat(instr->opc) == 1) || (opc_cat(instr->opc) == 6) || ir3_cat2_int(instr->opc) || (is_mad(instr->opc) && (n == 0))); if (new_flags & IR3_REG_SABS) iim_val = abs(iim_val); if (new_flags & IR3_REG_SNEG) iim_val = -iim_val; if (new_flags & IR3_REG_BNOT) iim_val = ~iim_val; /* other than category 1 (mov) we can only encode up to 10 bits: */ if ((instr->opc == OPC_MOV) || !((iim_val & ~0x3ff) && (-iim_val & ~0x3ff))) { new_flags &= ~(IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_BNOT); src_reg = ir3_reg_clone(instr->block->shader, src_reg); src_reg->flags = new_flags; src_reg->iim_val = iim_val; instr->regs[n+1] = src_reg; } else if (valid_flags(instr, n, (new_flags & ~IR3_REG_IMMED) | IR3_REG_CONST)) { /* See if lowering an immediate to const would help. */ instr->regs[n+1] = lower_immed(ctx, src_reg, new_flags); } return; } } }
std::shared_ptr<Texture> RenderPass:: get_buffer(std::string const& name, CameraMode mode, bool draw_fps) { // check for existance of desired buffer if ((mode == CENTER && center_eye_buffers_.find(name) == center_eye_buffers_.end()) || (mode == LEFT && left_eye_buffers_.find(name) == left_eye_buffers_.end()) || (mode == RIGHT && right_eye_buffers_.find(name) == right_eye_buffers_.end())) { WARNING("Failed to get buffer \"%s\" from pass \"%s\": " "A buffer with this name does not exist!", name.c_str(), get_name().c_str()); return NULL; } // return appropriate buffer if it has been rendered already if (mode == CENTER && rendererd_center_eye_) return center_eye_buffers_[name]; if (mode == LEFT && rendererd_left_eye_) return left_eye_buffers_[name]; if (mode == RIGHT && rendererd_right_eye_) return right_eye_buffers_[name]; // serialize the scenegraph Optimizer optimizer; optimizer.check(pipeline_->get_current_graph(), render_mask_); // if there are dynamic texture inputs for this render pass, get the // according buffers recursively for (auto& node: optimizer.get_data().nodes_) { auto material(inputs_.find(node.material_)); if (material != inputs_.end()) { for (auto& uniform: material->second) { overwrite_uniform_texture(material->first, uniform.first, pipeline_->get_render_pass(uniform.second.first)-> get_buffer(uniform.second.second, mode)); } } } // we'll need these two very often now... OptimizedScene const& scene(optimizer.get_data()); RenderContext const& ctx(pipeline_->get_context()); // get the fbo which should be rendered to FrameBufferObject* fbo(NULL); switch (mode) { case CENTER: fbo = ¢er_eye_fbo_; break; case LEFT: fbo = &left_eye_fbo_; break; case RIGHT: fbo = &right_eye_fbo_; break; } fbo->bind(ctx); fbo->clear_color_buffers(ctx); fbo->clear_depth_stencil_buffer(ctx); ctx.render_context->set_viewport(scm::gl::viewport(math::vec2(0,0), math::vec2(fbo->width(), fbo->height()))); auto camera_it(scene.cameras_.find(camera_)); auto screen_it(scene.screens_.find(screen_)); if (camera_it != scene.cameras_.end() && screen_it != scene.screens_.end()) { auto camera(camera_it->second); auto screen(screen_it->second); math::mat4 camera_transform(camera.transform_); if (mode == LEFT) { scm::math::translate(camera_transform, -camera.stereo_width_*0.5f, 0.f, 0.f); } else if (mode == RIGHT) { scm::math::translate(camera_transform, camera.stereo_width_*0.5f, 0.f, 0.f); } auto projection(math::compute_frustum(camera_transform.column(3), screen.transform_, 0.1, 100000.f)); math::mat4 view_transform(screen.transform_); view_transform[12] = 0.f; view_transform[13] = 0.f; view_transform[14] = 0.f; view_transform[15] = 1.f; math::vec3 camera_position(camera_transform.column(3)[0], camera_transform.column(3)[1], camera_transform.column(3)[2]); view_transform = scm::math::make_translation(camera_position) * view_transform; math::mat4 view_matrix(scm::math::inverse(view_transform)); // update light data uniform block if (scene.lights_.size() > 0) { if (!light_information_) { light_information_ = new scm::gl::uniform_block<LightInformation>(ctx.render_device); } light_information_->begin_manipulation(ctx.render_context); LightInformation light; light.light_count = math::vec4i(scene.lights_.size(), scene.lights_.size(), scene.lights_.size(), scene.lights_.size()); for (unsigned i(0); i < scene.lights_.size(); ++i) { math::mat4 transform(scene.lights_[i].transform_); // calc light radius and position light.position[i] = math::vec4(transform[12], transform[13], transform[14], transform[15]); float radius = scm::math::length(light.position[i] - transform * math::vec4(0.f, 0.f, 1.f, 1.f)); light.color_radius[i] = math::vec4(scene.lights_[i].color_.r(), scene.lights_[i].color_.g(), scene.lights_[i].color_.b(), radius); } **light_information_ = light; light_information_->end_manipulation(); ctx.render_context->bind_uniform_buffer( light_information_->block_buffer(), 0); } for (auto& core: scene.nodes_) { auto geometry = GeometryBase::instance()->get(core.geometry_); auto material = MaterialBase::instance()->get(core.material_); if (material && geometry) { material->use(ctx); if (float_uniforms_.find(core.material_) != float_uniforms_.end()) { for (auto val : float_uniforms_[core.material_]) material->get_shader()->set_float(ctx, val.first, val.second); } if (texture_uniforms_.find(core.material_) != texture_uniforms_.end()) { for (auto val : texture_uniforms_[core.material_]) material->get_shader()->set_sampler2D(ctx, val.first, *val.second); } material->get_shader()->set_mat4(ctx, "projection_matrix", projection); material->get_shader()->set_mat4(ctx, "view_matrix", view_matrix); material->get_shader()->set_mat4(ctx, "model_matrix", core.transform_); material->get_shader()->set_mat4(ctx, "normal_matrix", scm::math::transpose( scm::math::inverse(core.transform_))); geometry->draw(ctx); material->unuse(ctx); } else if (material) { WARNING("Cannot render geometry \"%s\": Undefined geometry " "name!", core.geometry_.c_str()); } else if (geometry) { WARNING("Cannot render geometry \"%s\": Undefined material " "name: \"%s\"!", core.geometry_.c_str(), core.material_.c_str()); } else { WARNING("Cannot render geometry \"%s\": Undefined geometry " "and material name: \"%s\"!", core.geometry_.c_str(), core.material_.c_str()); } } if (scene.lights_.size() > 0) { ctx.render_context->reset_uniform_buffers(); } } fbo->unbind(ctx); // draw fps on the screen if (draw_fps) { if (!text_renderer_) text_renderer_ = new TextRenderer(pipeline_->get_context()); if (mode == CENTER) { text_renderer_->render_fps(pipeline_->get_context(), center_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } else if (mode == LEFT) { text_renderer_->render_fps(pipeline_->get_context(), left_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } else { text_renderer_->render_fps(pipeline_->get_context(), right_eye_fbo_, pipeline_->get_application_fps(), pipeline_->get_rendering_fps()); } } // return the buffer and set the already-rendered-flag if (mode == CENTER) { rendererd_center_eye_ = true; return center_eye_buffers_[name]; } else if (mode == LEFT) { rendererd_left_eye_ = true; return left_eye_buffers_[name]; } else { rendererd_right_eye_ = true; return right_eye_buffers_[name]; } }
void Shader::disable(void) { unuse(); }
int main_w2(int base_in) { // use the input number to set the global variable _base_ = base_in; // see http://stackoverflow.com/questions/6792235/declaring-global-variable-array-inside-a-function-in-c // http://forum.codecall.net/topic/51010-dynamic-arrays-using-malloc-and-realloc/ used_number = (int *)malloc(sizeof(int*) * _base_); // seems need (int *); should not be under c99 if (used_number ==NULL) { printf("Error allocating memory!\n"); //print an error message return 1; //return with failure } // used_number[0] = 90; <-- remember to set it back to 0 if used // used_number[_base_ - 1] = 99; // test_used_number(0); // test_used_number(_base_ - 1); // used_number[0] = 0; // used_number[_base_ - 1] = 0; clock_t tick_l; int cnt_l = 0; int ab, cd, ef, gh; tick_l = clock(); reset_w2(); for (ab = START_WITH_2_ALWAYS * _base_; ab < (_base_ * _base_); ab++) // a cannot be 0 and 1, start from 20 if (use(ab)) { //try to use ab for (cd = START_WITH_2_ALWAYS * _base_; cd < ab; cd++) // ab > cd to avoid ef < 0 and cd run into ab if (use(cd)) { ef = ab - cd; // you do not need to loop over ef and gh gh = (1 * (_base_ * _base_ + _base_ + 1)) - ef; // a - b = c + d = p = 111 // fixed a and b then c and d is fixed by logic if (use(ef)) { if (use(gh)) { if (cnt_l < MAX_SOL_TO_PRINT) { printf("%d: %d - %d = %d, %d + %d = %d\n", cnt_l + 1, ab, cd, ef, ef, gh, (1 * (_base_ * _base_ + _base_ + 1)) ); } cnt_l++; // need that for those time you cannot print all unuse(gh); } unuse(ef); } unuse(cd); } unuse(ab); // if used(ab) unuse it } tick_l = clock()-tick_l; printf("\n_base_ is: %d\n", _base_); printf("time used: %f\n", ((double)tick_l)/CLOCKS_PER_SEC); // printf("MAX_SOL_TO_PRINT: %d\n\n", MAX_SOL_TO_PRINT); printf("number of solutions: %d\n\n", cnt_l); free(used_number); return 0; }