ADD: Texture Cache 2
This commit is contained in:
@@ -34,7 +34,23 @@ void TextureCache::cleanup()
|
|||||||
|
|
||||||
TextureCache::TextureHandle TextureCache::request(const TextureKey &key, VkSampler sampler)
|
TextureCache::TextureHandle TextureCache::request(const TextureKey &key, VkSampler sampler)
|
||||||
{
|
{
|
||||||
auto it = _lookup.find(key.hash);
|
// Ensure we have a valid, stable hash for deduplication.
|
||||||
|
TextureKey normKey = key;
|
||||||
|
if (normKey.hash == 0)
|
||||||
|
{
|
||||||
|
if (normKey.kind == TextureKey::SourceKind::FilePath)
|
||||||
|
{
|
||||||
|
std::string id = std::string("PATH:") + normKey.path + (normKey.srgb ? "#sRGB" : "#UNORM");
|
||||||
|
normKey.hash = texcache::fnv1a64(id);
|
||||||
|
}
|
||||||
|
else if (!normKey.bytes.empty())
|
||||||
|
{
|
||||||
|
uint64_t h = texcache::fnv1a64(normKey.bytes.data(), normKey.bytes.size());
|
||||||
|
normKey.hash = h ^ (normKey.srgb ? 0x9E3779B97F4A7C15ull : 0ull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = _lookup.find(normKey.hash);
|
||||||
if (it != _lookup.end())
|
if (it != _lookup.end())
|
||||||
{
|
{
|
||||||
TextureHandle h = it->second;
|
TextureHandle h = it->second;
|
||||||
@@ -47,19 +63,19 @@ TextureCache::TextureHandle TextureCache::request(const TextureKey &key, VkSampl
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle h = static_cast<TextureHandle>(_entries.size());
|
TextureHandle h = static_cast<TextureHandle>(_entries.size());
|
||||||
_lookup.emplace(key.hash, h);
|
_lookup.emplace(normKey.hash, h);
|
||||||
|
|
||||||
Entry e{};
|
Entry e{};
|
||||||
e.key = key;
|
e.key = normKey;
|
||||||
e.sampler = sampler;
|
e.sampler = sampler;
|
||||||
e.state = EntryState::Unloaded;
|
e.state = EntryState::Unloaded;
|
||||||
if (key.kind == TextureKey::SourceKind::FilePath)
|
if (normKey.kind == TextureKey::SourceKind::FilePath)
|
||||||
{
|
{
|
||||||
e.path = key.path;
|
e.path = normKey.path;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
e.bytes = key.bytes;
|
e.bytes = normKey.bytes;
|
||||||
}
|
}
|
||||||
_entries.push_back(std::move(e));
|
_entries.push_back(std::move(e));
|
||||||
return h;
|
return h;
|
||||||
@@ -198,15 +214,28 @@ void TextureCache::pumpLoads(ResourceManager &rm, FrameResources &)
|
|||||||
// Simple throttle to avoid massive spikes.
|
// Simple throttle to avoid massive spikes.
|
||||||
const int kMaxLoadsPerPump = 4;
|
const int kMaxLoadsPerPump = 4;
|
||||||
int started = 0;
|
int started = 0;
|
||||||
|
const uint32_t now = _context ? _context->frameIndex : 0u;
|
||||||
for (auto &e : _entries)
|
for (auto &e : _entries)
|
||||||
{
|
{
|
||||||
if (e.state == EntryState::Unloaded)
|
if (e.state == EntryState::Unloaded)
|
||||||
|
{
|
||||||
|
// Visibility-driven residency: only start uploads for textures
|
||||||
|
// that were marked used recently (current or previous frame).
|
||||||
|
// This avoids uploading assets that are not visible.
|
||||||
|
bool recentlyUsed = true;
|
||||||
|
if (_context)
|
||||||
|
{
|
||||||
|
// Schedule when first seen (previous frame) or if seen again.
|
||||||
|
recentlyUsed = (now == 0u) || (now - e.lastUsedFrame <= 1u);
|
||||||
|
}
|
||||||
|
if (recentlyUsed)
|
||||||
{
|
{
|
||||||
start_load(e, rm);
|
start_load(e, rm);
|
||||||
if (++started >= kMaxLoadsPerPump) break;
|
if (++started >= kMaxLoadsPerPump) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextureCache::evictToBudget(size_t budgetBytes)
|
void TextureCache::evictToBudget(size_t budgetBytes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,6 +170,22 @@ void GeometryPass::draw_geometry(VkCommandBuffer cmd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Texture visibility-driven residency
|
||||||
|
if (ctxLocal->textures && !opaque_draws.empty())
|
||||||
|
{
|
||||||
|
std::unordered_set<VkDescriptorSet> seen;
|
||||||
|
seen.reserve(opaque_draws.size());
|
||||||
|
for (uint32_t idx : opaque_draws)
|
||||||
|
{
|
||||||
|
const RenderObject &r = mainDrawContext.OpaqueSurfaces[idx];
|
||||||
|
VkDescriptorSet set = r.material ? r.material->materialSet : VK_NULL_HANDLE;
|
||||||
|
if (set != VK_NULL_HANDLE && seen.insert(set).second)
|
||||||
|
{
|
||||||
|
ctxLocal->textures->markSetUsed(set, ctxLocal->frameIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::sort(opaque_draws.begin(), opaque_draws.end(), [&](const auto &iA, const auto &iB)
|
std::sort(opaque_draws.begin(), opaque_draws.end(), [&](const auto &iA, const auto &iB)
|
||||||
{
|
{
|
||||||
const RenderObject &A = mainDrawContext.OpaqueSurfaces[iA];
|
const RenderObject &A = mainDrawContext.OpaqueSurfaces[iA];
|
||||||
|
|||||||
Reference in New Issue
Block a user