VideoCommon: update resource manager with a material/shader/and texture(+sampler) resource to show the complexities that warrant the resource manager system

This commit is contained in:
iwubcode
2025-11-23 11:08:50 -06:00
parent 23c637c029
commit 5c00f07074
11 changed files with 1199 additions and 15 deletions
@@ -3,6 +3,11 @@
#include "VideoCommon/Resources/CustomResourceManager.h"
#include "Common/Logging/Log.h"
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/PipelineUtils.h"
#include "VideoCommon/Resources/InvalidTextures.h"
#include "VideoCommon/VideoEvents.h"
namespace VideoCommon
@@ -10,22 +15,46 @@ namespace VideoCommon
void CustomResourceManager::Initialize()
{
m_asset_cache.Initialize();
m_worker_thread.Reset("resource-worker");
m_host_config.bits = ShaderHostConfig::GetCurrent().bits;
m_async_shader_compiler = g_gfx->CreateAsyncShaderCompiler();
m_async_shader_compiler->StartWorkerThreads(1); // TODO expose to config
m_xfb_event =
AfterFrameEvent::Register([this](Core::System&) { XFBTriggered(); }, "CustomResourceManager");
GetVideoEvents().after_frame_event.Register([this](Core::System&) { XFBTriggered(); });
m_invalid_array_texture = CreateInvalidArrayTexture();
m_invalid_color_texture = CreateInvalidColorTexture();
m_invalid_cubemap_texture = CreateInvalidCubemapTexture();
m_invalid_transparent_texture = CreateInvalidTransparentTexture();
}
void CustomResourceManager::Shutdown()
{
if (m_async_shader_compiler)
m_async_shader_compiler->StopWorkerThreads();
m_asset_cache.Shutdown();
m_worker_thread.Shutdown();
Reset();
}
void CustomResourceManager::Reset()
{
m_material_resources.clear();
m_shader_resources.clear();
m_texture_data_resources.clear();
m_texture_sampler_resources.clear();
m_invalid_transparent_texture.reset();
m_invalid_color_texture.reset();
m_invalid_cubemap_texture.reset();
m_invalid_array_texture.reset();
m_asset_cache.Reset();
m_texture_pool.Reset();
m_worker_thread.Reset("resource-worker");
}
void CustomResourceManager::MarkAssetDirty(const CustomAssetLibrary::AssetID& asset_id)
@@ -38,24 +67,99 @@ void CustomResourceManager::XFBTriggered()
m_asset_cache.Update();
}
void CustomResourceManager::SetHostConfig(const ShaderHostConfig& host_config)
{
for (auto& [id, shader_resources] : m_shader_resources)
{
for (auto& [key, shader_resource] : shader_resources)
{
shader_resource->SetHostConfig(host_config);
// Hack to get access to resource internals
Resource* resource = shader_resource.get();
// Tell shader and references to trigger a reload
// on next usage
resource->NotifyAssetChanged(false);
}
}
m_host_config.bits = host_config.bits;
}
TextureDataResource* CustomResourceManager::GetTextureDataFromAsset(
const CustomAssetLibrary::AssetID& asset_id,
std::shared_ptr<VideoCommon::CustomAssetLibrary> library)
{
const auto [it, added] = m_texture_data_resources.try_emplace(asset_id, nullptr);
if (added)
auto& resource = m_texture_data_resources[asset_id];
if (resource == nullptr)
{
it->second = std::make_unique<TextureDataResource>(CreateResourceContext(asset_id, library));
resource =
std::make_unique<TextureDataResource>(CreateResourceContext(asset_id, std::move(library)));
}
ProcessResource(it->second.get());
return it->second.get();
ProcessResource(resource.get());
return resource.get();
}
MaterialResource* CustomResourceManager::GetMaterialFromAsset(
const CustomAssetLibrary::AssetID& asset_id, const GXPipelineUid& pipeline_uid,
std::shared_ptr<VideoCommon::CustomAssetLibrary> library)
{
auto& resource = m_material_resources[asset_id][PipelineToHash(pipeline_uid)];
if (resource == nullptr)
{
resource = std::make_unique<MaterialResource>(
CreateResourceContext(asset_id, std::move(library)), pipeline_uid);
}
ProcessResource(resource.get());
return resource.get();
}
ShaderResource*
CustomResourceManager::GetShaderFromAsset(const CustomAssetLibrary::AssetID& asset_id,
std::size_t shader_key, const GXPipelineUid& pipeline_uid,
const std::string& preprocessor_settings,
std::shared_ptr<VideoCommon::CustomAssetLibrary> library)
{
auto& resource = m_shader_resources[asset_id][shader_key];
if (resource == nullptr)
{
resource = std::make_unique<ShaderResource>(CreateResourceContext(asset_id, std::move(library)),
pipeline_uid, preprocessor_settings, m_host_config);
}
ProcessResource(resource.get());
return resource.get();
}
TextureAndSamplerResource* CustomResourceManager::GetTextureAndSamplerFromAsset(
const CustomAssetLibrary::AssetID& asset_id,
std::shared_ptr<VideoCommon::CustomAssetLibrary> library)
{
auto& resource = m_texture_sampler_resources[asset_id];
if (resource == nullptr)
{
resource = std::make_unique<TextureAndSamplerResource>(
CreateResourceContext(asset_id, std::move(library)));
}
ProcessResource(resource.get());
return resource.get();
}
Resource::ResourceContext CustomResourceManager::CreateResourceContext(
const CustomAssetLibrary::AssetID& asset_id,
const std::shared_ptr<VideoCommon::CustomAssetLibrary>& library)
std::shared_ptr<VideoCommon::CustomAssetLibrary> library)
{
return Resource::ResourceContext{asset_id, library, &m_asset_cache, this};
return Resource::ResourceContext{asset_id,
std::move(library),
&m_asset_cache,
this,
&m_texture_pool,
&m_worker_thread,
m_async_shader_compiler.get(),
m_invalid_array_texture.get(),
m_invalid_color_texture.get(),
m_invalid_cubemap_texture.get(),
m_invalid_transparent_texture.get()};
}
void CustomResourceManager::ProcessResource(Resource* resource)
@@ -71,18 +175,15 @@ void CustomResourceManager::ProcessResource(Resource* resource)
return;
}
// Early out if we're already at our end state
if (resource->GetState() == Resource::State::DataAvailable)
return;
ProcessResourceState(resource);
}
void CustomResourceManager::ProcessResourceState(Resource* resource)
{
Resource::State next_state = resource->GetState();
const auto current_state = resource->GetState();
Resource::State next_state = current_state;
Resource::TaskComplete task_complete = Resource::TaskComplete::No;
switch (resource->GetState())
switch (current_state)
{
case Resource::State::ReloadData:
resource->ResetData();
@@ -102,6 +203,14 @@ void CustomResourceManager::ProcessResourceState(Resource* resource)
case Resource::State::ProcessingData:
task_complete = resource->ProcessData();
next_state = Resource::State::DataAvailable;
break;
case Resource::State::DataAvailable:
// Early out, we're already at our end state
return;
default:
ERROR_LOG_FMT(VIDEO, "Unknown resource state '{}' for resource '{}'",
static_cast<int>(current_state), resource->m_resource_context.primary_asset_id);
return;
};
if (task_complete == Resource::TaskComplete::Yes)