gl_compute_pipeline: Force context flush when loading shader cache

This commit is contained in:
ameerj 2023-01-29 21:04:46 -05:00
parent 01eeda74a6
commit 720ff38097
4 changed files with 37 additions and 7 deletions

View file

@ -30,7 +30,7 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep
ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_,
BufferCache& buffer_cache_, ProgramManager& program_manager_,
const Shader::Info& info_, std::string code,
std::vector<u32> code_v)
std::vector<u32> code_v, bool force_context_flush)
: texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
program_manager{program_manager_}, info{info_} {
switch (device.GetShaderBackend()) {
@ -63,6 +63,15 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac
writes_global_memory = !use_storage_buffers &&
std::ranges::any_of(info.storage_buffers_descriptors,
[](const auto& desc) { return desc.is_written; });
if (force_context_flush) {
std::scoped_lock lock{built_mutex};
built_fence.Create();
// Flush this context to ensure compilation commands and fence are in the GPU pipe.
glFlush();
built_condvar.notify_one();
} else {
is_built = true;
}
}
void ComputePipeline::Configure() {
@ -142,6 +151,9 @@ void ComputePipeline::Configure() {
}
texture_cache.FillComputeImageViews(std::span(views.data(), views.size()));
if (!is_built) {
WaitForBuild();
}
if (assembly_program.handle != 0) {
program_manager.BindComputeAssemblyProgram(assembly_program.handle);
} else {
@ -223,4 +235,13 @@ void ComputePipeline::Configure() {
}
}
void ComputePipeline::WaitForBuild() {
if (built_fence.handle == 0) {
std::unique_lock lock{built_mutex};
built_condvar.wait(lock, [this] { return built_fence.handle != 0; });
}
ASSERT(glClientWaitSync(built_fence.handle, 0, GL_TIMEOUT_IGNORED) != GL_WAIT_FAILED);
is_built = true;
}
} // namespace OpenGL

View file

@ -50,7 +50,8 @@ class ComputePipeline {
public:
explicit ComputePipeline(const Device& device, TextureCache& texture_cache_,
BufferCache& buffer_cache_, ProgramManager& program_manager_,
const Shader::Info& info_, std::string code, std::vector<u32> code_v);
const Shader::Info& info_, std::string code, std::vector<u32> code_v,
bool force_context_flush = false);
void Configure();
@ -65,6 +66,8 @@ public:
}
private:
void WaitForBuild();
TextureCache& texture_cache;
BufferCache& buffer_cache;
Tegra::MemoryManager* gpu_memory;
@ -81,6 +84,11 @@ private:
bool use_storage_buffers{};
bool writes_global_memory{};
std::mutex built_mutex;
std::condition_variable built_condvar;
OGLSync built_fence{};
bool is_built{false};
};
} // namespace OpenGL

View file

@ -286,7 +286,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
file.read(reinterpret_cast<char*>(&key), sizeof(key));
queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
ctx->pools.ReleaseContents();
auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)};
std::scoped_lock lock{state.mutex};
if (pipeline) {
compute_cache.emplace(key, std::move(pipeline));
@ -560,8 +560,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
}
std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
ShaderContext::ShaderPools& pools, const ComputePipelineKey& key,
Shader::Environment& env) try {
ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env,
bool force_context_flush) try {
LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash());
Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()};
@ -590,7 +590,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
}
return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager,
program.info, code, code_spirv);
program.info, code, code_spirv, force_context_flush);
} catch (Shader::Exception& exception) {
LOG_ERROR(Render_OpenGL, "{}", exception.what());
return nullptr;

View file

@ -58,7 +58,8 @@ private:
std::unique_ptr<ComputePipeline> CreateComputePipeline(ShaderContext::ShaderPools& pools,
const ComputePipelineKey& key,
Shader::Environment& env);
Shader::Environment& env,
bool force_context_flush = false);
std::unique_ptr<ShaderWorker> CreateWorkers() const;