Merge pull request #2383 from ReinUsesLisp/aoffi-test
gl_shader_decompiler: Disable variable AOFFI on unsupported devices
This commit is contained in:
commit
4fad91ca45
11 changed files with 161 additions and 73 deletions
|
@ -36,6 +36,8 @@ add_library(video_core STATIC
|
||||||
renderer_base.h
|
renderer_base.h
|
||||||
renderer_opengl/gl_buffer_cache.cpp
|
renderer_opengl/gl_buffer_cache.cpp
|
||||||
renderer_opengl/gl_buffer_cache.h
|
renderer_opengl/gl_buffer_cache.h
|
||||||
|
renderer_opengl/gl_device.cpp
|
||||||
|
renderer_opengl/gl_device.h
|
||||||
renderer_opengl/gl_global_cache.cpp
|
renderer_opengl/gl_global_cache.cpp
|
||||||
renderer_opengl/gl_global_cache.h
|
renderer_opengl/gl_global_cache.h
|
||||||
renderer_opengl/gl_primitive_assembler.cpp
|
renderer_opengl/gl_primitive_assembler.cpp
|
||||||
|
|
45
src/video_core/renderer_opengl/gl_device.cpp
Normal file
45
src/video_core/renderer_opengl/gl_device.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename T>
|
||||||
|
T GetInteger(GLenum pname) {
|
||||||
|
GLint temporary;
|
||||||
|
glGetIntegerv(pname, &temporary);
|
||||||
|
return static_cast<T>(temporary);
|
||||||
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
Device::Device() {
|
||||||
|
uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||||
|
has_variable_aoffi = TestVariableAoffi();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::TestVariableAoffi() {
|
||||||
|
const GLchar* AOFFI_TEST = R"(#version 430 core
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform ivec2 variable_offset;
|
||||||
|
void main() {
|
||||||
|
gl_Position = textureOffset(tex, vec2(0), variable_offset);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &AOFFI_TEST)};
|
||||||
|
GLint link_status{};
|
||||||
|
glGetProgramiv(shader, GL_LINK_STATUS, &link_status);
|
||||||
|
glDeleteProgram(shader);
|
||||||
|
|
||||||
|
const bool supported{link_status == GL_TRUE};
|
||||||
|
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", supported);
|
||||||
|
return supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace OpenGL
|
30
src/video_core/renderer_opengl/gl_device.h
Normal file
30
src/video_core/renderer_opengl/gl_device.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
|
||||||
|
class Device {
|
||||||
|
public:
|
||||||
|
Device();
|
||||||
|
|
||||||
|
std::size_t GetUniformBufferAlignment() const {
|
||||||
|
return uniform_buffer_alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasVariableAoffi() const {
|
||||||
|
return has_variable_aoffi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool TestVariableAoffi();
|
||||||
|
|
||||||
|
std::size_t uniform_buffer_alignment{};
|
||||||
|
bool has_variable_aoffi{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace OpenGL
|
|
@ -99,7 +99,7 @@ struct FramebufferCacheKey {
|
||||||
};
|
};
|
||||||
|
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
||||||
: res_cache{*this}, shader_cache{*this, system}, global_cache{*this}, system{system},
|
: res_cache{*this}, shader_cache{*this, system, device}, global_cache{*this}, system{system},
|
||||||
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
|
||||||
OpenGLState::ApplyDefaultState();
|
OpenGLState::ApplyDefaultState();
|
||||||
|
|
||||||
|
@ -107,8 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
|
||||||
state.draw.shader_program = 0;
|
state.draw.shader_program = 0;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
|
|
||||||
|
|
||||||
LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
|
LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
|
||||||
CheckExtensions();
|
CheckExtensions();
|
||||||
}
|
}
|
||||||
|
@ -315,8 +313,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
||||||
|
|
||||||
GLShader::MaxwellUniformData ubo{};
|
GLShader::MaxwellUniformData ubo{};
|
||||||
ubo.SetFromRegs(gpu, stage);
|
ubo.SetFromRegs(gpu, stage);
|
||||||
const GLintptr offset = buffer_cache.UploadHostMemory(
|
const GLintptr offset =
|
||||||
&ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
|
buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
|
||||||
|
|
||||||
// Bind the emulation info buffer
|
// Bind the emulation info buffer
|
||||||
bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset,
|
bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset,
|
||||||
|
@ -700,23 +698,24 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
// Add space for index buffer (keeping in mind non-core primitives)
|
// Add space for index buffer (keeping in mind non-core primitives)
|
||||||
switch (regs.draw.topology) {
|
switch (regs.draw.topology) {
|
||||||
case Maxwell::PrimitiveTopology::Quads:
|
case Maxwell::PrimitiveTopology::Quads:
|
||||||
buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) +
|
buffer_size = Common::AlignUp(buffer_size, 4) +
|
||||||
primitive_assembler.CalculateQuadSize(regs.vertex_buffer.count);
|
primitive_assembler.CalculateQuadSize(regs.vertex_buffer.count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (is_indexed) {
|
if (is_indexed) {
|
||||||
buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) + CalculateIndexBufferSize();
|
buffer_size = Common::AlignUp(buffer_size, 4) + CalculateIndexBufferSize();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uniform space for the 5 shader stages
|
// Uniform space for the 5 shader stages
|
||||||
buffer_size =
|
buffer_size = Common::AlignUp<std::size_t>(buffer_size, 4) +
|
||||||
Common::AlignUp<std::size_t>(buffer_size, 4) +
|
(sizeof(GLShader::MaxwellUniformData) + device.GetUniformBufferAlignment()) *
|
||||||
(sizeof(GLShader::MaxwellUniformData) + uniform_buffer_alignment) * Maxwell::MaxShaderStage;
|
Maxwell::MaxShaderStage;
|
||||||
|
|
||||||
// Add space for at least 18 constant buffers
|
// Add space for at least 18 constant buffers
|
||||||
buffer_size += Maxwell::MaxConstBuffers * (MaxConstbufferSize + uniform_buffer_alignment);
|
buffer_size +=
|
||||||
|
Maxwell::MaxConstBuffers * (MaxConstbufferSize + device.GetUniformBufferAlignment());
|
||||||
|
|
||||||
const bool invalidate = buffer_cache.Map(buffer_size);
|
const bool invalidate = buffer_cache.Map(buffer_size);
|
||||||
if (invalidate) {
|
if (invalidate) {
|
||||||
|
@ -848,8 +847,8 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader
|
||||||
size = Common::AlignUp(size, sizeof(GLvec4));
|
size = Common::AlignUp(size, sizeof(GLvec4));
|
||||||
ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
|
ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
|
||||||
|
|
||||||
const GLintptr const_buffer_offset = buffer_cache.UploadMemory(
|
const GLintptr const_buffer_offset =
|
||||||
buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment));
|
buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment());
|
||||||
|
|
||||||
bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size);
|
bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "video_core/rasterizer_cache.h"
|
#include "video_core/rasterizer_cache.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/renderer_opengl/gl_buffer_cache.h"
|
#include "video_core/renderer_opengl/gl_buffer_cache.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
#include "video_core/renderer_opengl/gl_global_cache.h"
|
#include "video_core/renderer_opengl/gl_global_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
|
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
|
||||||
|
@ -172,6 +173,7 @@ private:
|
||||||
/// but are needed for correct emulation
|
/// but are needed for correct emulation
|
||||||
void CheckExtensions();
|
void CheckExtensions();
|
||||||
|
|
||||||
|
const Device device;
|
||||||
OpenGLState state;
|
OpenGLState state;
|
||||||
|
|
||||||
RasterizerCacheOpenGL res_cache;
|
RasterizerCacheOpenGL res_cache;
|
||||||
|
@ -180,7 +182,6 @@ private:
|
||||||
SamplerCacheOpenGL sampler_cache;
|
SamplerCacheOpenGL sampler_cache;
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
ScreenInfo& screen_info;
|
ScreenInfo& screen_info;
|
||||||
|
|
||||||
std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
|
std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
|
||||||
|
@ -196,7 +197,6 @@ private:
|
||||||
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
|
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
|
||||||
OGLBufferCache buffer_cache;
|
OGLBufferCache buffer_cache;
|
||||||
PrimitiveAssembler primitive_assembler{buffer_cache};
|
PrimitiveAssembler primitive_assembler{buffer_cache};
|
||||||
GLint uniform_buffer_alignment;
|
|
||||||
|
|
||||||
BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
|
BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
|
||||||
BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
|
BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
|
||||||
|
|
|
@ -136,8 +136,8 @@ u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode&
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an unspecialized program from code streams
|
/// Creates an unspecialized program from code streams
|
||||||
GLShader::ProgramResult CreateProgram(Maxwell::ShaderProgram program_type, ProgramCode program_code,
|
GLShader::ProgramResult CreateProgram(const Device& device, Maxwell::ShaderProgram program_type,
|
||||||
ProgramCode program_code_b) {
|
ProgramCode program_code, ProgramCode program_code_b) {
|
||||||
GLShader::ShaderSetup setup(program_code);
|
GLShader::ShaderSetup setup(program_code);
|
||||||
if (program_type == Maxwell::ShaderProgram::VertexA) {
|
if (program_type == Maxwell::ShaderProgram::VertexA) {
|
||||||
// VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders.
|
// VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders.
|
||||||
|
@ -151,11 +151,11 @@ GLShader::ProgramResult CreateProgram(Maxwell::ShaderProgram program_type, Progr
|
||||||
switch (program_type) {
|
switch (program_type) {
|
||||||
case Maxwell::ShaderProgram::VertexA:
|
case Maxwell::ShaderProgram::VertexA:
|
||||||
case Maxwell::ShaderProgram::VertexB:
|
case Maxwell::ShaderProgram::VertexB:
|
||||||
return GLShader::GenerateVertexShader(setup);
|
return GLShader::GenerateVertexShader(device, setup);
|
||||||
case Maxwell::ShaderProgram::Geometry:
|
case Maxwell::ShaderProgram::Geometry:
|
||||||
return GLShader::GenerateGeometryShader(setup);
|
return GLShader::GenerateGeometryShader(device, setup);
|
||||||
case Maxwell::ShaderProgram::Fragment:
|
case Maxwell::ShaderProgram::Fragment:
|
||||||
return GLShader::GenerateFragmentShader(setup);
|
return GLShader::GenerateFragmentShader(device, setup);
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type));
|
LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type));
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -214,22 +214,20 @@ std::set<GLenum> GetSupportedFormats() {
|
||||||
return supported_formats;
|
return supported_formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier,
|
CachedShader::CachedShader(const Device& device, VAddr cpu_addr, u64 unique_identifier,
|
||||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||||
const PrecompiledPrograms& precompiled_programs,
|
const PrecompiledPrograms& precompiled_programs,
|
||||||
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr)
|
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr)
|
||||||
: RasterizerCacheObject{host_ptr}, host_ptr{host_ptr}, cpu_addr{cpu_addr},
|
: RasterizerCacheObject{host_ptr}, host_ptr{host_ptr}, cpu_addr{cpu_addr},
|
||||||
unique_identifier{unique_identifier}, program_type{program_type}, disk_cache{disk_cache},
|
unique_identifier{unique_identifier}, program_type{program_type}, disk_cache{disk_cache},
|
||||||
precompiled_programs{precompiled_programs} {
|
precompiled_programs{precompiled_programs} {
|
||||||
|
const std::size_t code_size{CalculateProgramSize(program_code)};
|
||||||
const std::size_t code_size = CalculateProgramSize(program_code);
|
const std::size_t code_size_b{program_code_b.empty() ? 0
|
||||||
const std::size_t code_size_b =
|
: CalculateProgramSize(program_code_b)};
|
||||||
program_code_b.empty() ? 0 : CalculateProgramSize(program_code_b);
|
GLShader::ProgramResult program_result{
|
||||||
|
CreateProgram(device, program_type, program_code, program_code_b)};
|
||||||
GLShader::ProgramResult program_result =
|
|
||||||
CreateProgram(program_type, program_code, program_code_b);
|
|
||||||
if (program_result.first.empty()) {
|
if (program_result.first.empty()) {
|
||||||
// TODO(Rodrigo): Unimplemented shader stages hit here, avoid using these for now
|
// TODO(Rodrigo): Unimplemented shader stages hit here, avoid using these for now
|
||||||
return;
|
return;
|
||||||
|
@ -253,7 +251,6 @@ CachedShader::CachedShader(VAddr cpu_addr, u64 unique_identifier,
|
||||||
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier},
|
: RasterizerCacheObject{host_ptr}, cpu_addr{cpu_addr}, unique_identifier{unique_identifier},
|
||||||
program_type{program_type}, disk_cache{disk_cache}, precompiled_programs{
|
program_type{program_type}, disk_cache{disk_cache}, precompiled_programs{
|
||||||
precompiled_programs} {
|
precompiled_programs} {
|
||||||
|
|
||||||
code = std::move(result.first);
|
code = std::move(result.first);
|
||||||
entries = result.second;
|
entries = result.second;
|
||||||
shader_length = entries.shader_length;
|
shader_length = entries.shader_length;
|
||||||
|
@ -346,8 +343,9 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode,
|
||||||
return {unique_identifier, base_bindings, primitive_mode};
|
return {unique_identifier, base_bindings, primitive_mode};
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system)
|
ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
|
||||||
: RasterizerCache{rasterizer}, disk_cache{system} {}
|
const Device& device)
|
||||||
|
: RasterizerCache{rasterizer}, disk_cache{system}, device{device} {}
|
||||||
|
|
||||||
void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
const VideoCore::DiskResourceLoadCallback& callback) {
|
const VideoCore::DiskResourceLoadCallback& callback) {
|
||||||
|
@ -441,17 +439,18 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia
|
||||||
const std::unordered_map<u64, ShaderDiskCacheDecompiled>& decompiled) {
|
const std::unordered_map<u64, ShaderDiskCacheDecompiled>& decompiled) {
|
||||||
std::unordered_map<u64, UnspecializedShader> unspecialized;
|
std::unordered_map<u64, UnspecializedShader> unspecialized;
|
||||||
|
|
||||||
if (callback)
|
if (callback) {
|
||||||
callback(VideoCore::LoadCallbackStage::Decompile, 0, raws.size());
|
callback(VideoCore::LoadCallbackStage::Decompile, 0, raws.size());
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < raws.size(); ++i) {
|
for (std::size_t i = 0; i < raws.size(); ++i) {
|
||||||
if (stop_loading)
|
if (stop_loading) {
|
||||||
return {};
|
return {};
|
||||||
|
}
|
||||||
const auto& raw{raws[i]};
|
const auto& raw{raws[i]};
|
||||||
const u64 unique_identifier = raw.GetUniqueIdentifier();
|
const u64 unique_identifier{raw.GetUniqueIdentifier()};
|
||||||
const u64 calculated_hash =
|
const u64 calculated_hash{
|
||||||
GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB());
|
GetUniqueIdentifier(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB())};
|
||||||
if (unique_identifier != calculated_hash) {
|
if (unique_identifier != calculated_hash) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
Render_OpenGL,
|
Render_OpenGL,
|
||||||
|
@ -468,8 +467,8 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia
|
||||||
result = {stored_decompiled.code, stored_decompiled.entries};
|
result = {stored_decompiled.code, stored_decompiled.entries};
|
||||||
} else {
|
} else {
|
||||||
// Otherwise decompile the shader at boot and save the result to the decompiled file
|
// Otherwise decompile the shader at boot and save the result to the decompiled file
|
||||||
result =
|
result = CreateProgram(device, raw.GetProgramType(), raw.GetProgramCode(),
|
||||||
CreateProgram(raw.GetProgramType(), raw.GetProgramCode(), raw.GetProgramCodeB());
|
raw.GetProgramCodeB());
|
||||||
disk_cache.SaveDecompiled(unique_identifier, result.first, result.second);
|
disk_cache.SaveDecompiled(unique_identifier, result.first, result.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,8 +478,9 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia
|
||||||
{raw.GetUniqueIdentifier(),
|
{raw.GetUniqueIdentifier(),
|
||||||
{std::move(result.first), std::move(result.second), raw.GetProgramType()}});
|
{std::move(result.first), std::move(result.second), raw.GetProgramType()}});
|
||||||
|
|
||||||
if (callback)
|
if (callback) {
|
||||||
callback(VideoCore::LoadCallbackStage::Decompile, i, raws.size());
|
callback(VideoCore::LoadCallbackStage::Decompile, i, raws.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return unspecialized;
|
return unspecialized;
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
||||||
precompiled_programs, found->second, host_ptr);
|
precompiled_programs, found->second, host_ptr);
|
||||||
} else {
|
} else {
|
||||||
shader = std::make_shared<CachedShader>(
|
shader = std::make_shared<CachedShader>(
|
||||||
cpu_addr, unique_identifier, program, disk_cache, precompiled_programs,
|
device, cpu_addr, unique_identifier, program, disk_cache, precompiled_programs,
|
||||||
std::move(program_code), std::move(program_code_b), host_ptr);
|
std::move(program_code), std::move(program_code_b), host_ptr);
|
||||||
}
|
}
|
||||||
Register(shader);
|
Register(shader);
|
||||||
|
|
|
@ -27,6 +27,7 @@ class System;
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
class CachedShader;
|
class CachedShader;
|
||||||
|
class Device;
|
||||||
class RasterizerOpenGL;
|
class RasterizerOpenGL;
|
||||||
struct UnspecializedShader;
|
struct UnspecializedShader;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ using PrecompiledShaders = std::unordered_map<u64, GLShader::ProgramResult>;
|
||||||
|
|
||||||
class CachedShader final : public RasterizerCacheObject {
|
class CachedShader final : public RasterizerCacheObject {
|
||||||
public:
|
public:
|
||||||
explicit CachedShader(VAddr cpu_addr, u64 unique_identifier,
|
explicit CachedShader(const Device& device, VAddr cpu_addr, u64 unique_identifier,
|
||||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||||
const PrecompiledPrograms& precompiled_programs,
|
const PrecompiledPrograms& precompiled_programs,
|
||||||
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr);
|
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr);
|
||||||
|
@ -112,7 +113,8 @@ private:
|
||||||
|
|
||||||
class ShaderCacheOpenGL final : public RasterizerCache<Shader> {
|
class ShaderCacheOpenGL final : public RasterizerCache<Shader> {
|
||||||
public:
|
public:
|
||||||
explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system);
|
explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
|
||||||
|
const Device& device);
|
||||||
|
|
||||||
/// Loads disk cache for the current game
|
/// Loads disk cache for the current game
|
||||||
void LoadDiskCache(const std::atomic_bool& stop_loading,
|
void LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
|
@ -130,6 +132,8 @@ private:
|
||||||
CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump,
|
CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump,
|
||||||
const std::set<GLenum>& supported_formats);
|
const std::set<GLenum>& supported_formats);
|
||||||
|
|
||||||
|
const Device& device;
|
||||||
|
|
||||||
std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
|
std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
|
||||||
|
|
||||||
ShaderDiskCacheOpenGL disk_cache;
|
ShaderDiskCacheOpenGL disk_cache;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
@ -135,8 +136,9 @@ bool IsPrecise(Node node) {
|
||||||
|
|
||||||
class GLSLDecompiler final {
|
class GLSLDecompiler final {
|
||||||
public:
|
public:
|
||||||
explicit GLSLDecompiler(const ShaderIR& ir, ShaderStage stage, std::string suffix)
|
explicit GLSLDecompiler(const Device& device, const ShaderIR& ir, ShaderStage stage,
|
||||||
: ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {}
|
std::string suffix)
|
||||||
|
: device{device}, ir{ir}, stage{stage}, suffix{suffix}, header{ir.GetHeader()} {}
|
||||||
|
|
||||||
void Decompile() {
|
void Decompile() {
|
||||||
DeclareVertex();
|
DeclareVertex();
|
||||||
|
@ -802,8 +804,12 @@ private:
|
||||||
// Inline the string as an immediate integer in GLSL (AOFFI arguments are required
|
// Inline the string as an immediate integer in GLSL (AOFFI arguments are required
|
||||||
// to be constant by the standard).
|
// to be constant by the standard).
|
||||||
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
|
expr += std::to_string(static_cast<s32>(immediate->GetValue()));
|
||||||
} else {
|
} else if (device.HasVariableAoffi()) {
|
||||||
|
// Avoid using variable AOFFI on unsupported devices.
|
||||||
expr += "ftoi(" + Visit(operand) + ')';
|
expr += "ftoi(" + Visit(operand) + ')';
|
||||||
|
} else {
|
||||||
|
// Insert 0 on devices not supporting variable AOFFI.
|
||||||
|
expr += '0';
|
||||||
}
|
}
|
||||||
if (index + 1 < aoffi.size()) {
|
if (index + 1 < aoffi.size()) {
|
||||||
expr += ", ";
|
expr += ", ";
|
||||||
|
@ -1645,6 +1651,7 @@ private:
|
||||||
return name + '_' + std::to_string(index) + '_' + suffix;
|
return name + '_' + std::to_string(index) + '_' + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Device& device;
|
||||||
const ShaderIR& ir;
|
const ShaderIR& ir;
|
||||||
const ShaderStage stage;
|
const ShaderStage stage;
|
||||||
const std::string suffix;
|
const std::string suffix;
|
||||||
|
@ -1676,8 +1683,9 @@ std::string GetCommonDeclarations() {
|
||||||
"}\n";
|
"}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramResult Decompile(const ShaderIR& ir, Maxwell::ShaderStage stage, const std::string& suffix) {
|
ProgramResult Decompile(const Device& device, const ShaderIR& ir, Maxwell::ShaderStage stage,
|
||||||
GLSLDecompiler decompiler(ir, stage, suffix);
|
const std::string& suffix) {
|
||||||
|
GLSLDecompiler decompiler(device, ir, stage, suffix);
|
||||||
decompiler.Decompile();
|
decompiler.Decompile();
|
||||||
return {decompiler.GetResult(), decompiler.GetShaderEntries()};
|
return {decompiler.GetResult(), decompiler.GetShaderEntries()};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
class Device;
|
||||||
|
}
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
class ShaderIR;
|
class ShaderIR;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +81,7 @@ struct ShaderEntries {
|
||||||
|
|
||||||
std::string GetCommonDeclarations();
|
std::string GetCommonDeclarations();
|
||||||
|
|
||||||
ProgramResult Decompile(const VideoCommon::Shader::ShaderIR& ir, Maxwell::ShaderStage stage,
|
ProgramResult Decompile(const Device& device, const VideoCommon::Shader::ShaderIR& ir,
|
||||||
const std::string& suffix);
|
Maxwell::ShaderStage stage, const std::string& suffix);
|
||||||
|
|
||||||
} // namespace OpenGL::GLShader
|
} // namespace OpenGL::GLShader
|
||||||
|
|
|
@ -16,7 +16,7 @@ using VideoCommon::Shader::ShaderIR;
|
||||||
|
|
||||||
static constexpr u32 PROGRAM_OFFSET{10};
|
static constexpr u32 PROGRAM_OFFSET{10};
|
||||||
|
|
||||||
ProgramResult GenerateVertexShader(const ShaderSetup& setup) {
|
ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup) {
|
||||||
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
||||||
|
|
||||||
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||||
|
@ -34,14 +34,15 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
|
||||||
|
|
||||||
)";
|
)";
|
||||||
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
||||||
ProgramResult program = Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
|
ProgramResult program =
|
||||||
|
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
|
||||||
|
|
||||||
out += program.first;
|
out += program.first;
|
||||||
|
|
||||||
if (setup.IsDualProgram()) {
|
if (setup.IsDualProgram()) {
|
||||||
ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
|
ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
|
||||||
ProgramResult program_b =
|
ProgramResult program_b =
|
||||||
Decompile(program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
|
Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
|
||||||
|
|
||||||
out += program_b.first;
|
out += program_b.first;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +76,7 @@ void main() {
|
||||||
return {out, program.second};
|
return {out, program.second};
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
|
ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) {
|
||||||
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
||||||
|
|
||||||
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||||
|
@ -95,7 +96,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
|
||||||
)";
|
)";
|
||||||
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
||||||
ProgramResult program =
|
ProgramResult program =
|
||||||
Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
|
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
|
||||||
out += program.first;
|
out += program.first;
|
||||||
|
|
||||||
out += R"(
|
out += R"(
|
||||||
|
@ -106,7 +107,7 @@ void main() {
|
||||||
return {out, program.second};
|
return {out, program.second};
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
|
ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) {
|
||||||
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
|
||||||
|
|
||||||
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||||
|
@ -158,7 +159,7 @@ bool AlphaFunc(in float value) {
|
||||||
)";
|
)";
|
||||||
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
||||||
ProgramResult program =
|
ProgramResult program =
|
||||||
Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
|
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
|
||||||
|
|
||||||
out += program.first;
|
out += program.first;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
|
||||||
|
namespace OpenGL {
|
||||||
|
class Device;
|
||||||
|
}
|
||||||
|
|
||||||
namespace OpenGL::GLShader {
|
namespace OpenGL::GLShader {
|
||||||
|
|
||||||
using VideoCommon::Shader::ProgramCode;
|
using VideoCommon::Shader::ProgramCode;
|
||||||
|
@ -39,22 +43,13 @@ private:
|
||||||
bool has_program_b{};
|
bool has_program_b{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/// Generates the GLSL vertex shader program source code for the given VS program
|
||||||
* Generates the GLSL vertex shader program source code for the given VS program
|
ProgramResult GenerateVertexShader(const Device& device, const ShaderSetup& setup);
|
||||||
* @returns String of the shader source code
|
|
||||||
*/
|
|
||||||
ProgramResult GenerateVertexShader(const ShaderSetup& setup);
|
|
||||||
|
|
||||||
/**
|
/// Generates the GLSL geometry shader program source code for the given GS program
|
||||||
* Generates the GLSL geometry shader program source code for the given GS program
|
ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup);
|
||||||
* @returns String of the shader source code
|
|
||||||
*/
|
|
||||||
ProgramResult GenerateGeometryShader(const ShaderSetup& setup);
|
|
||||||
|
|
||||||
/**
|
/// Generates the GLSL fragment shader program source code for the given FS program
|
||||||
* Generates the GLSL fragment shader program source code for the given FS program
|
ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup);
|
||||||
* @returns String of the shader source code
|
|
||||||
*/
|
|
||||||
ProgramResult GenerateFragmentShader(const ShaderSetup& setup);
|
|
||||||
|
|
||||||
} // namespace OpenGL::GLShader
|
} // namespace OpenGL::GLShader
|
||||||
|
|
Loading…
Reference in a new issue