| 189 | } |
| 190 | |
| 191 | Ref<Texture> TextBankGL33::Load(RStringB name) |
| 192 | { |
| 193 | int i = Find(name); |
| 194 | if (i >= 0) |
| 195 | return _texture[i].GetLink(); |
| 196 | |
| 197 | // Cache-miss texture load triggers PAA/PAC decode and a sequence of |
| 198 | // per-mip GL uploads — one of the top-three first-touch hitch sources. |
| 199 | // Scoped per-call so the recursive load chain a model triggers shows up |
| 200 | // as a stack of PERF lines, one per texture. See |
| 201 | const auto _perfTexLoadStart = ::Poseidon::Dev::Perf::Now(); |
| 202 | |
| 203 | int iFree = _texture.Size(); |
| 204 | |
| 205 | // Check existence against the loose-resolved path so a p3d-referenced |
| 206 | // .pac that has a .png/.tga/.jpg sibling on disk still loads. |
| 207 | RString resolved = Poseidon::Graphics::ResolveLooseTexturePath(name); |
| 208 | if (!QIFStreamB::FileExist(resolved)) |
| 209 | { |
| 210 | // A genuinely missing texture file is silently replaced by the default |
| 211 | // (placeholder) texture in the caller, so a broken/incomplete asset set |
| 212 | // is invisible at runtime. Surface it at WARN so it shows up in logs. |
| 213 | // Not ERROR: dangling texture refs are endemic in the original data |
| 214 | // (e.g. data\oblacno.pac, o\guns\beretta_bmp.pac) and the engine has |
| 215 | // always tolerated them with the default texture; promoting them to a |
| 216 | // --strict abort kills the stock game/viewer on its own assets. |
| 217 | // Procedural names (#...) have no backing file and are not asset errors. |
| 218 | const char* cname = static_cast<const char*>(name); |
| 219 | if (cname && cname[0] && cname[0] != '#') |
| 220 | LOG_WARN(Graphics, "GL33: Cannot load texture {}", cname); |
| 221 | else |
| 222 | LOG_DEBUG(Graphics, "GL33: Cannot load texture {}", cname); |
| 223 | return nullptr; |
| 224 | } |
| 225 | |
| 226 | Ref<TextureGL33> texture = new TextureGL33; |
| 227 | if (!texture) |
| 228 | return nullptr; |
| 229 | |
| 230 | if (texture->Init(name)) |
| 231 | return nullptr; |
| 232 | |
| 233 | _texture.Access(iFree); |
| 234 | TextureGL33* txt = texture; |
| 235 | _texture[iFree] = txt; |
| 236 | |
| 237 | const double _perfTexLoadMs = ::Poseidon::Dev::Perf::ElapsedMs(_perfTexLoadStart); |
| 238 | if (_perfTexLoadMs >= 0.5) |
| 239 | { |
| 240 | LOG_DEBUG(Graphics, "PERF: TextBank::Load {} took {:.2f}ms", static_cast<const char*>(name), _perfTexLoadMs); |
| 241 | } |
| 242 | ::Poseidon::Dev::Perf::EmitTraceEventAsset(Poseidon::Foundation::LogCategory::Graphics, "TextBank::Load", |
| 243 | _perfTexLoadStart, static_cast<const char*>(name)); |
| 244 | return txt; |
| 245 | } |
| 246 | |
| 247 | Ref<Texture> TextBankGL33::LoadInterpolated(RStringB n1, RStringB n2, float factor) |
| 248 | { |
nothing calls this directly
no test coverage detected