GrTexture* GrLockCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap, const GrTextureParams* params) { GrTexture* result = NULL; if (!bitmap.isVolatile()) { // If the bitmap isn't changing try to find a cached copy first uint64_t key = bitmap.getGenerationID(); key |= ((uint64_t) bitmap.pixelRefOffset()) << 32; GrTextureDesc desc; desc.fWidth = bitmap.width(); desc.fHeight = bitmap.height(); desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap.config()); GrCacheData cacheData(key); result = ctx->findAndLockTexture(desc, cacheData, params); if (NULL == result) { result = sk_gr_create_bitmap_texture(ctx, key, params, bitmap); } } else { result = sk_gr_create_bitmap_texture(ctx, GrCacheData::kScratch_CacheID, params, bitmap); } if (NULL == result) { GrPrintf("---- failed to create texture for cache [%d %d]\n", bitmap.width(), bitmap.height()); } return result; }
//======================================================================================== TileCache_cl::TileCache_cl(string sDirectory) { setDirectory(sDirectory) ; cacheData() ; }
void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { ADD_COMMAND_GL(glDrawBuffers); _params.push_back(cacheData(n * sizeof(GLenum), bufs)); _params.push_back(n); DO_IT_NOW(_glDrawBuffers, 2); }
void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) { ADD_COMMAND_GL(glUniform4fv); const int VEC4_SIZE = 4 * sizeof(float); _params.push_back(cacheData(count * VEC4_SIZE, value)); _params.push_back(count); _params.push_back(location); DO_IT_NOW(_glUniform4fv, 3); }
/////////////////////////////////////////////////////////////////////////////// // Main LaserScan callback /////////////////////////////////////////////////////////////////////////////// void LineExtractionROS::laserScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg) { if (!data_cached_) { cacheData(scan_msg); data_cached_ = true; } std::vector<double> scan_ranges_doubles(scan_msg->ranges.begin(), scan_msg->ranges.end()); line_extraction_.setRangeData(scan_ranges_doubles); }
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); const int MATRIX4_SIZE = 16 * sizeof(float); _params.push_back(cacheData(count * MATRIX4_SIZE, value)); _params.push_back(transpose); _params.push_back(count); _params.push_back(location); DO_IT_NOW(_glUniformMatrix4fv, 4); }
void GrTextureStripAtlas::lockTexture() { GrTextureParams params; GrTextureDesc texDesc; texDesc.fWidth = fDesc.fWidth; texDesc.fHeight = fDesc.fHeight; texDesc.fConfig = fDesc.fConfig; GrCacheData cacheData(fCacheID); cacheData.fResourceDomain = GetTextureStripAtlasDomain(); fTexture = fDesc.fContext->findAndLockTexture(texDesc, cacheData, ¶ms); if (NULL == fTexture) { fTexture = fDesc.fContext->createAndLockTexture(¶ms, texDesc, cacheData, NULL, 0); // This is a new texture, so all of our cache info is now invalid this->initLRU(); fKeyTable.rewind(); } GrAssert(NULL != fTexture); }
bool SubplanRunner::runSubplans() { // This is what we annotate with the index selections and then turn into a solution. auto_ptr<OrMatchExpression> theOr( static_cast<OrMatchExpression*>(_query->root()->shallowClone())); // This is the skeleton of index selections that is inserted into the cache. auto_ptr<PlanCacheIndexTree> cacheData(new PlanCacheIndexTree()); for (size_t i = 0; i < theOr->numChildren(); ++i) { MatchExpression* orChild = theOr->getChild(i); auto_ptr<CanonicalQuery> orChildCQ(_cqs.front()); _cqs.pop(); // 'solutions' is owned by the SubplanRunner instance until // it is popped from the queue. vector<QuerySolution*> solutions = _solutions.front(); _solutions.pop(); // We already checked for zero solutions in planSubqueries(...). invariant(!solutions.empty()); if (1 == solutions.size()) { // There is only one solution. Transfer ownership to an auto_ptr. auto_ptr<QuerySolution> autoSoln(solutions[0]); // We want a well-formed *indexed* solution. if (NULL == autoSoln->cacheData.get()) { // For example, we don't cache things for 2d indices. QLOG() << "Subplanner: No cache data for subchild " << orChild->toString(); return false; } if (SolutionCacheData::USE_INDEX_TAGS_SOLN != autoSoln->cacheData->solnType) { QLOG() << "Subplanner: No indexed cache data for subchild " << orChild->toString(); return false; } // Add the index assignments to our original query. Status tagStatus = QueryPlanner::tagAccordingToCache( orChild, autoSoln->cacheData->tree.get(), _indexMap); if (!tagStatus.isOK()) { QLOG() << "Subplanner: Failed to extract indices from subchild " << orChild->toString(); return false; } // Add the child's cache data to the cache data we're creating for the main query. cacheData->children.push_back(autoSoln->cacheData->tree->clone()); } else { // N solutions, rank them. Takes ownership of orChildCQ. // the working set will be shared by the candidate plans and owned by the runner WorkingSet* sharedWorkingSet = new WorkingSet(); MultiPlanStage* multiPlanStage = new MultiPlanStage(_collection, orChildCQ.get()); // Dump all the solutions into the MPR. for (size_t ix = 0; ix < solutions.size(); ++ix) { PlanStage* nextPlanRoot; verify(StageBuilder::build(_txn, _collection, *solutions[ix], sharedWorkingSet, &nextPlanRoot)); // Owns first two arguments multiPlanStage->addPlan(solutions[ix], nextPlanRoot, sharedWorkingSet); } multiPlanStage->pickBestPlan(); if (! multiPlanStage->bestPlanChosen()) { QLOG() << "Subplanner: Failed to pick best plan for subchild " << orChildCQ->toString(); return false; } Runner* mpr = new SingleSolutionRunner(_collection, orChildCQ.release(), multiPlanStage->bestSolution(), multiPlanStage, sharedWorkingSet); _underlyingRunner.reset(mpr); if (_killed) { QLOG() << "Subplanner: Killed while picking best plan for subchild " << orChild->toString(); return false; } QuerySolution* bestSoln = multiPlanStage->bestSolution(); if (SolutionCacheData::USE_INDEX_TAGS_SOLN != bestSoln->cacheData->solnType) { QLOG() << "Subplanner: No indexed cache data for subchild " << orChild->toString(); return false; } // Add the index assignments to our original query. Status tagStatus = QueryPlanner::tagAccordingToCache( orChild, bestSoln->cacheData->tree.get(), _indexMap); if (!tagStatus.isOK()) { QLOG() << "Subplanner: Failed to extract indices from subchild " << orChild->toString(); return false; } cacheData->children.push_back(bestSoln->cacheData->tree->clone()); } } // Must do this before using the planner functionality. sortUsingTags(theOr.get()); // Use the cached index assignments to build solnRoot. Takes ownership of 'theOr' QuerySolutionNode* solnRoot = QueryPlannerAccess::buildIndexedDataAccess( *_query, theOr.release(), false, _plannerParams.indices); if (NULL == solnRoot) { QLOG() << "Subplanner: Failed to build indexed data path for subplanned query\n"; return false; } QLOG() << "Subplanner: fully tagged tree is " << solnRoot->toString(); // Takes ownership of 'solnRoot' QuerySolution* soln = QueryPlannerAnalysis::analyzeDataAccess(*_query, _plannerParams, solnRoot); if (NULL == soln) { QLOG() << "Subplanner: Failed to analyze subplanned query"; return false; } // We want our franken-solution to be cached. SolutionCacheData* scd = new SolutionCacheData(); scd->tree.reset(cacheData.release()); soln->cacheData.reset(scd); QLOG() << "Subplanner: Composite solution is " << soln->toString() << endl; // We use one of these even if there is one plan. We do this so that the entry is cached // with stats obtained in the same fashion as a competitive ranking would have obtained // them. MultiPlanStage* multiPlanStage = new MultiPlanStage(_collection, _query.get()); WorkingSet* ws = new WorkingSet(); PlanStage* root; verify(StageBuilder::build(_txn, _collection, *soln, ws, &root)); multiPlanStage->addPlan(soln, root, ws); // Takes ownership first two arguments. multiPlanStage->pickBestPlan(); if (! multiPlanStage->bestPlanChosen()) { QLOG() << "Subplanner: Failed to pick best plan for subchild " << _query->toString(); return false; } Runner* mpr = new SingleSolutionRunner(_collection, _query.release(), multiPlanStage->bestSolution(), multiPlanStage, ws); _underlyingRunner.reset(mpr); return true; }
static GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, uint64_t key, const GrTextureParams* params, const SkBitmap& origBitmap) { SkAutoLockPixels alp(origBitmap); if (!origBitmap.readyToDraw()) { return NULL; } SkBitmap tmpBitmap; const SkBitmap* bitmap = &origBitmap; GrTextureDesc desc; desc.fWidth = bitmap->width(); desc.fHeight = bitmap->height(); desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config()); GrCacheData cacheData(key); if (SkBitmap::kIndex8_Config == bitmap->config()) { // build_compressed_data doesn't do npot->pot expansion // and paletted textures can't be sub-updated if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) { size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize; SkAutoMalloc storage(imagesize); build_compressed_data(storage.get(), origBitmap); // our compressed data will be trimmed, so pass width() for its // "rowBytes", since they are the same now. if (GrCacheData::kScratch_CacheID != key) { return ctx->createAndLockTexture(params, desc, cacheData, storage.get(), bitmap->width()); } else { GrTexture* result = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); result->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, storage.get()); return result; } } else { origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); // now bitmap points to our temp, which has been promoted to 32bits bitmap = &tmpBitmap; } } desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config()); if (GrCacheData::kScratch_CacheID != key) { // This texture is likely to be used again so leave it in the cache // but locked. return ctx->createAndLockTexture(params, desc, cacheData, bitmap->getPixels(), bitmap->rowBytes()); } else { // This texture is unlikely to be used again (in its present form) so // just use a scratch texture. This will remove the texture from the // cache so no one else can find it. Additionally, once unlocked, the // scratch texture will go to the end of the list for purging so will // likely be available for this volatile bitmap the next time around. GrTexture* result = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); result->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, bitmap->getPixels(), bitmap->rowBytes()); return result; } }
void StaticMesh::Create(const char* fileName) { char baseDir[256]; char fileNameWoExt[256]; char tempPath[256]; _splitpath_s(fileName, nullptr, 0, baseDir, sizeof(baseDir), fileNameWoExt, sizeof(baseDir), nullptr, 0); // キャッシュファイル名 snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt); std::ifstream cacheFile(tempPath, std::ios::in | std::ios::binary); if (cacheFile) { /** キャッシュから読み込み **/ // ファイル全体をリード cacheFile.seekg(0, std::fstream::end); uint32_t eofPos = (uint32_t)cacheFile.tellg(); cacheFile.clear(); cacheFile.seekg(0, std::fstream::beg); uint32_t begPos = (uint32_t)cacheFile.tellg(); uint32_t size = eofPos - begPos; std::unique_ptr<uint8_t> cacheData(new uint8_t[size]); cacheFile.read((char*)cacheData.get(), size); // パース const CacheHeader* header = (CacheHeader*)cacheData.get(); const Shape* shapes = (Shape*)(cacheData.get() + header->offsetToShapes); shapes_.resize(header->shapeNum); memcpy(&shapes_[0], shapes, sizeof(Shape) * header->shapeNum); uint32_t vtxStride = ComputeVertexStride(header->vertexAttrs); vertexBuffer_.Create(cacheData.get() + header->offsetToVertices, vtxStride * header->vertexNum, header->vertexAttrs); indexBuffer_.Create(cacheData.get() + header->offsetToIndeces, sizeof(uint32_t) * header->vertexNum, INDEX_BUFFER_STRIDE_U32); const char* materials = (const char*)(cacheData.get() + header->offsetToMaterial); materials_.resize(header->materialNum); std::unordered_map<std::string, uint32_t> textureMap; for (size_t i = 0; i < (uint32_t)materials_.size(); i++) { const char* m = materials + (256 * i); ZeroMemory(&materials_[i], sizeof(materials_[i])); // テクスチャ検索 if (strlen(m) > 0) { Texture* texture = nullptr; auto iter = textureMap.find(m); if (iter != textureMap.end()) { texture = textures_[iter->second]; } else { texture = new Texture(); snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m); texture->LoadFromFile(tempPath); textures_.push_back(texture); uint32_t index = (uint32_t)textures_.size() - 1; textureMap[m] = index; } materials_[i].albedo = texture; } } } else { /** キャッシュがなかったらobjを読み込み **/ tinyobj::attrib_t attrib; std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; Printf("Loading %s\n", fileName); std::string err; if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, fileName, baseDir, true)) { if (!err.empty()) { Printf(err.c_str()); } Printf("Failed to load/parse .obj.\n"); return; } //Printf("# of vertices : %d\n", (attrib.vertices.size() / 3)); //Printf("# of normals : %d\n", (attrib.normals.size() / 3)); //Printf("# of texcoords : %d\n", (attrib.texcoords.size() / 2)); //Printf("# of shapes : %d\n", shapes.size()); //Printf("# of materials : %d\n", materials.size()); // 現状はすべてのシェイプで頂点構造が一致している前提で処理しているため1つの頂点バッファにすべて入っている // TODO:tangent, bitangent計算 uint32_t vtxAttrs = VERTEX_ATTR_FLAG_POSITION; vtxAttrs |= (attrib.normals.size() > 0) ? VERTEX_ATTR_FLAG_NORMAL : 0; vtxAttrs |= (attrib.texcoords.size() > 0) ? VERTEX_ATTR_FLAG_TEXCOORD0 : 0; uint32_t vtxStride = ComputeVertexStride(vtxAttrs); // 全インデックス数を計算 uint32_t totalIndexNum = 0; for (auto& shape : shapes) { totalIndexNum += static_cast<uint32_t>(shape.mesh.indices.size()); } // 頂点をインデックス展開するためトータルインデックス数分の頂点バッファを確保 std::unique_ptr<uint8_t> vertexData(new uint8_t[vtxStride * totalIndexNum]); std::unique_ptr<uint8_t> indexData(new uint8_t[sizeof(uint32_t) * totalIndexNum]); uint32_t currentIndex = 0; uint32_t* currentIndexBufferPtr = reinterpret_cast<uint32_t*>(indexData.get()); for (uint32_t i = 0; i < shapes.size(); i++) { auto& shape = shapes[i]; Assert(shape.mesh.num_face_vertices.size() == shape.mesh.material_ids.size()); // For each face uint32_t currentMaterial = 0xffffffff; Shape currentShape; for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) { Assert(shape.mesh.num_face_vertices[f] == 3); // 三角形化済みのはず // マテリアルの切り替わり判定 if (currentMaterial != shape.mesh.material_ids[f]) { if (currentMaterial != 0xffffffff) { currentShape.indexCount = currentIndex - currentShape.indexStart; shapes_.push_back(currentShape); } currentMaterial = shape.mesh.material_ids[f]; currentShape.materialIndex = currentMaterial; currentShape.indexStart = currentIndex; currentShape.indexCount = 0; } // For each vertex in the face uint32_t ptrOffset = 0; uint8_t* currentVertexBufferPtr = vertexData.get() + (vtxStride * currentIndex); for (size_t v = 0; v < 3; v++) { tinyobj::index_t idx = shape.mesh.indices[(f * 3) + v]; // position memcpy(currentVertexBufferPtr + ptrOffset, &attrib.vertices[idx.vertex_index * 3], 12); ptrOffset += 12; // normal if (vtxAttrs & VERTEX_ATTR_FLAG_NORMAL) { memcpy(currentVertexBufferPtr + ptrOffset, &attrib.normals[idx.normal_index * 3], 12); ptrOffset += 12; } // texcoord if (vtxAttrs & VERTEX_ATTR_FLAG_TEXCOORD0) { float2* uv = reinterpret_cast<float2*>(currentVertexBufferPtr + ptrOffset); uv->x = attrib.texcoords[idx.texcoord_index * 2 + 0]; uv->y = 1.0f - attrib.texcoords[idx.texcoord_index * 2 + 1]; // OpenGL -> DirectX ptrOffset += 8; } currentIndexBufferPtr[currentIndex] = currentIndex; currentIndex++; } } // 最後のマテリアル分追加 currentShape.indexCount = currentIndex - currentShape.indexStart; shapes_.push_back(currentShape); } vertexBuffer_.Create(vertexData.get(), vtxStride * totalIndexNum, vtxAttrs); indexBuffer_.Create(indexData.get(), sizeof(uint32_t) * totalIndexNum, INDEX_BUFFER_STRIDE_U32); // マテリアル materials_.resize(materials.size()); std::unordered_map<std::string, uint32_t> textureMap; for (size_t i = 0; i < (uint32_t)materials_.size(); i++) { auto& m = materials[i]; ZeroMemory(&materials_[i], sizeof(materials_[i])); // テクスチャ検索 if (m.diffuse_texname.size() > 0) { Texture* texture = nullptr; auto iter = textureMap.find(m.diffuse_texname); if (iter != textureMap.end()) { texture = textures_[iter->second]; } else { texture = new Texture(); snprintf(tempPath, sizeof(tempPath), "%s%s", baseDir, m.diffuse_texname.c_str()); texture->LoadFromFile(tempPath); textures_.push_back(texture); uint32_t index = (uint32_t)textures_.size() - 1; textureMap[m.diffuse_texname] = index; } materials_[i].albedo = texture; } } // 読み込み高速化のためのキャッシュデータを生成 { snprintf(tempPath, sizeof(tempPath), "%s%s.cache", baseDir, fileNameWoExt); std::ofstream file(tempPath, std::ios::out | std::ios::binary); CacheHeader header; header.shapeNum = (uint16_t)shapes_.size(); header.materialNum = (uint16_t)materials_.size(); header.vertexAttrs = (uint16_t)vtxAttrs; header.vertexNum = totalIndexNum; header.offsetToShapes = sizeof(CacheHeader); header.offsetToVertices = header.offsetToShapes + sizeof(Shape) * header.shapeNum; header.offsetToIndeces = header.offsetToVertices + (vtxStride * totalIndexNum); header.offsetToMaterial = header.offsetToIndeces + (sizeof(uint32_t) * totalIndexNum); file.write((char*)&header, sizeof(header)); // シェイプ for (auto& s : shapes_) { file.write((char*)&s, sizeof(s)); } // 頂点 file.write((char*)vertexData.get(), vtxStride * totalIndexNum); // インデックス file.write((char*)indexData.get(), sizeof(uint32_t) * totalIndexNum); // マテリアル for (auto& m : materials) { FillMemory(tempPath, sizeof(tempPath), 0); snprintf(tempPath, sizeof(tempPath), "%s", m.diffuse_texname.c_str()); file.write(tempPath, sizeof(tempPath)); } } } }