|
|
|
@ -29,6 +29,7 @@
|
|
|
|
|
#include "video_core/shader/memory_util.h"
|
|
|
|
|
#include "video_core/shader/registry.h"
|
|
|
|
|
#include "video_core/shader/shader_ir.h"
|
|
|
|
|
#include "video_core/shader_cache.h"
|
|
|
|
|
|
|
|
|
|
namespace OpenGL {
|
|
|
|
|
|
|
|
|
@ -194,12 +195,9 @@ std::unordered_set<GLenum> GetSupportedFormats() {
|
|
|
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
|
|
CachedShader::CachedShader(VAddr cpu_addr, std::size_t size_in_bytes,
|
|
|
|
|
std::shared_ptr<VideoCommon::Shader::Registry> registry,
|
|
|
|
|
ShaderEntries entries, ProgramSharedPtr program_)
|
|
|
|
|
: RasterizerCacheObject{cpu_addr}, registry{std::move(registry)}, entries{std::move(entries)},
|
|
|
|
|
size_in_bytes{size_in_bytes}, program{std::move(program_)} {
|
|
|
|
|
// Assign either the assembly program or source program. We can't have both.
|
|
|
|
|
Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries,
|
|
|
|
|
ProgramSharedPtr program)
|
|
|
|
|
: registry{std::move(registry)}, entries{std::move(entries)}, program{std::move(program)} {
|
|
|
|
|
handle = program->assembly_program.handle;
|
|
|
|
|
if (handle == 0) {
|
|
|
|
|
handle = program->source_program.handle;
|
|
|
|
@ -207,16 +205,16 @@ CachedShader::CachedShader(VAddr cpu_addr, std::size_t size_in_bytes,
|
|
|
|
|
ASSERT(handle != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CachedShader::~CachedShader() = default;
|
|
|
|
|
Shader::~Shader() = default;
|
|
|
|
|
|
|
|
|
|
GLuint CachedShader::GetHandle() const {
|
|
|
|
|
GLuint Shader::GetHandle() const {
|
|
|
|
|
DEBUG_ASSERT(registry->IsConsistent());
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
|
|
|
|
|
Maxwell::ShaderProgram program_type, ProgramCode code,
|
|
|
|
|
ProgramCode code_b) {
|
|
|
|
|
std::unique_ptr<Shader> Shader::CreateStageFromMemory(const ShaderParameters& params,
|
|
|
|
|
Maxwell::ShaderProgram program_type,
|
|
|
|
|
ProgramCode code, ProgramCode code_b) {
|
|
|
|
|
const auto shader_type = GetShaderType(program_type);
|
|
|
|
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
|
|
|
|
|
|
|
|
@ -241,12 +239,12 @@ Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
|
|
|
|
|
entry.bindless_samplers = registry->GetBindlessSamplers();
|
|
|
|
|
params.disk_cache.SaveEntry(std::move(entry));
|
|
|
|
|
|
|
|
|
|
return std::shared_ptr<CachedShader>(
|
|
|
|
|
new CachedShader(params.cpu_addr, size_in_bytes, std::move(registry),
|
|
|
|
|
MakeEntries(params.device, ir, shader_type), std::move(program)));
|
|
|
|
|
return std::unique_ptr<Shader>(new Shader(
|
|
|
|
|
std::move(registry), MakeEntries(params.device, ir, shader_type), std::move(program)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, ProgramCode code) {
|
|
|
|
|
std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params,
|
|
|
|
|
ProgramCode code) {
|
|
|
|
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
|
|
|
|
|
|
|
|
|
auto& engine = params.system.GPU().KeplerCompute();
|
|
|
|
@ -266,23 +264,23 @@ Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, Prog
|
|
|
|
|
entry.bindless_samplers = registry->GetBindlessSamplers();
|
|
|
|
|
params.disk_cache.SaveEntry(std::move(entry));
|
|
|
|
|
|
|
|
|
|
return std::shared_ptr<CachedShader>(
|
|
|
|
|
new CachedShader(params.cpu_addr, size_in_bytes, std::move(registry),
|
|
|
|
|
MakeEntries(params.device, ir, ShaderType::Compute), std::move(program)));
|
|
|
|
|
return std::unique_ptr<Shader>(new Shader(std::move(registry),
|
|
|
|
|
MakeEntries(params.device, ir, ShaderType::Compute),
|
|
|
|
|
std::move(program)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader CachedShader::CreateFromCache(const ShaderParameters& params,
|
|
|
|
|
const PrecompiledShader& precompiled_shader,
|
|
|
|
|
std::size_t size_in_bytes) {
|
|
|
|
|
return std::shared_ptr<CachedShader>(
|
|
|
|
|
new CachedShader(params.cpu_addr, size_in_bytes, precompiled_shader.registry,
|
|
|
|
|
precompiled_shader.entries, precompiled_shader.program));
|
|
|
|
|
std::unique_ptr<Shader> Shader::CreateFromCache(const ShaderParameters& params,
|
|
|
|
|
const PrecompiledShader& precompiled_shader) {
|
|
|
|
|
return std::unique_ptr<Shader>(new Shader(
|
|
|
|
|
precompiled_shader.registry, precompiled_shader.entries, precompiled_shader.program));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
|
|
|
|
|
Core::Frontend::EmuWindow& emu_window, const Device& device)
|
|
|
|
|
: RasterizerCache{rasterizer}, system{system}, emu_window{emu_window}, device{device},
|
|
|
|
|
disk_cache{system} {}
|
|
|
|
|
: VideoCommon::ShaderCache<Shader>{rasterizer}, system{system},
|
|
|
|
|
emu_window{emu_window}, device{device}, disk_cache{system} {}
|
|
|
|
|
|
|
|
|
|
ShaderCacheOpenGL::~ShaderCacheOpenGL() = default;
|
|
|
|
|
|
|
|
|
|
void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
|
|
|
|
const VideoCore::DiskResourceLoadCallback& callback) {
|
|
|
|
@ -436,7 +434,7 @@ ProgramSharedPtr ShaderCacheOpenGL::GeneratePrecompiledProgram(
|
|
|
|
|
return program;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
|
|
|
|
Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
|
|
|
|
if (!system.GPU().Maxwell3D().dirty.flags[Dirty::Shaders]) {
|
|
|
|
|
return last_shaders[static_cast<std::size_t>(program)];
|
|
|
|
|
}
|
|
|
|
@ -446,8 +444,7 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
|
|
|
|
|
|
|
|
|
// Look up shader in the cache based on address
|
|
|
|
|
const auto cpu_addr{memory_manager.GpuToCpuAddress(address)};
|
|
|
|
|
Shader shader{cpu_addr ? TryGet(*cpu_addr) : null_shader};
|
|
|
|
|
if (shader) {
|
|
|
|
|
if (Shader* const shader{cpu_addr ? TryGet(*cpu_addr) : null_shader.get()}) {
|
|
|
|
|
return last_shaders[static_cast<std::size_t>(program)] = shader;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -468,30 +465,29 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
|
|
|
|
const ShaderParameters params{system, disk_cache, device,
|
|
|
|
|
*cpu_addr, host_ptr, unique_identifier};
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Shader> shader;
|
|
|
|
|
const auto found = runtime_cache.find(unique_identifier);
|
|
|
|
|
if (found == runtime_cache.end()) {
|
|
|
|
|
shader = CachedShader::CreateStageFromMemory(params, program, std::move(code),
|
|
|
|
|
std::move(code_b));
|
|
|
|
|
shader = Shader::CreateStageFromMemory(params, program, std::move(code), std::move(code_b));
|
|
|
|
|
} else {
|
|
|
|
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
|
|
|
|
shader = CachedShader::CreateFromCache(params, found->second, size_in_bytes);
|
|
|
|
|
shader = Shader::CreateFromCache(params, found->second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader* const result = shader.get();
|
|
|
|
|
if (cpu_addr) {
|
|
|
|
|
Register(shader);
|
|
|
|
|
Register(std::move(shader), *cpu_addr, code.size() * sizeof(u64));
|
|
|
|
|
} else {
|
|
|
|
|
null_shader = shader;
|
|
|
|
|
null_shader = std::move(shader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return last_shaders[static_cast<std::size_t>(program)] = shader;
|
|
|
|
|
return last_shaders[static_cast<std::size_t>(program)] = result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) {
|
|
|
|
|
Shader* ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) {
|
|
|
|
|
auto& memory_manager{system.GPU().MemoryManager()};
|
|
|
|
|
const auto cpu_addr{memory_manager.GpuToCpuAddress(code_addr)};
|
|
|
|
|
|
|
|
|
|
auto kernel = cpu_addr ? TryGet(*cpu_addr) : null_kernel;
|
|
|
|
|
if (kernel) {
|
|
|
|
|
if (Shader* const kernel = cpu_addr ? TryGet(*cpu_addr) : null_kernel.get()) {
|
|
|
|
|
return kernel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -503,20 +499,21 @@ Shader ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) {
|
|
|
|
|
const ShaderParameters params{system, disk_cache, device,
|
|
|
|
|
*cpu_addr, host_ptr, unique_identifier};
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Shader> kernel;
|
|
|
|
|
const auto found = runtime_cache.find(unique_identifier);
|
|
|
|
|
if (found == runtime_cache.end()) {
|
|
|
|
|
kernel = CachedShader::CreateKernelFromMemory(params, std::move(code));
|
|
|
|
|
kernel = Shader::CreateKernelFromMemory(params, std::move(code));
|
|
|
|
|
} else {
|
|
|
|
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
|
|
|
|
kernel = CachedShader::CreateFromCache(params, found->second, size_in_bytes);
|
|
|
|
|
kernel = Shader::CreateFromCache(params, found->second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Shader* const result = kernel.get();
|
|
|
|
|
if (cpu_addr) {
|
|
|
|
|
Register(kernel);
|
|
|
|
|
Register(std::move(kernel), *cpu_addr, code.size() * sizeof(u64));
|
|
|
|
|
} else {
|
|
|
|
|
null_kernel = kernel;
|
|
|
|
|
null_kernel = std::move(kernel);
|
|
|
|
|
}
|
|
|
|
|
return kernel;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace OpenGL
|
|
|
|
|