video_core: Replace gl_shader_decompiler

This commit is contained in:
ReinUsesLisp 2018-12-20 22:29:15 -03:00
parent 0c6fb456e0
commit a4f052f6b3
8 changed files with 58 additions and 4186 deletions

View File

@ -42,8 +42,6 @@ add_library(video_core STATIC
renderer_opengl/gl_resource_manager.h renderer_opengl/gl_resource_manager.h
renderer_opengl/gl_shader_cache.cpp renderer_opengl/gl_shader_cache.cpp
renderer_opengl/gl_shader_cache.h renderer_opengl/gl_shader_cache.h
renderer_opengl/gl_shader_decompiler.cpp
renderer_opengl/gl_shader_decompiler.h
renderer_opengl/gl_shader_gen.cpp renderer_opengl/gl_shader_gen.cpp
renderer_opengl/gl_shader_gen.h renderer_opengl/gl_shader_gen.h
renderer_opengl/gl_shader_manager.cpp renderer_opengl/gl_shader_manager.cpp

View File

@ -925,7 +925,7 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
const auto& gpu = Core::System::GetInstance().GPU(); const auto& gpu = Core::System::GetInstance().GPU();
const auto& maxwell3d = gpu.Maxwell3D(); const auto& maxwell3d = gpu.Maxwell3D();
const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)]; const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
const auto& entries = shader->GetShaderEntries().const_buffer_entries; const auto& entries = shader->GetShaderEntries().const_buffers;
constexpr u64 max_binds = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers; constexpr u64 max_binds = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers;
std::array<GLuint, max_binds> bind_buffers; std::array<GLuint, max_binds> bind_buffers;
@ -993,7 +993,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
MICROPROFILE_SCOPE(OpenGL_Texture); MICROPROFILE_SCOPE(OpenGL_Texture);
const auto& gpu = Core::System::GetInstance().GPU(); const auto& gpu = Core::System::GetInstance().GPU();
const auto& maxwell3d = gpu.Maxwell3D(); const auto& maxwell3d = gpu.Maxwell3D();
const auto& entries = shader->GetShaderEntries().texture_samplers; const auto& entries = shader->GetShaderEntries().samplers;
ASSERT_MSG(current_unit + entries.size() <= std::size(state.texture_units), ASSERT_MSG(current_unit + entries.size() <= std::size(state.texture_units),
"Exceeded the number of active textures."); "Exceeded the number of active textures.");

View File

@ -12,9 +12,13 @@
#include "video_core/renderer_opengl/gl_shader_cache.h" #include "video_core/renderer_opengl/gl_shader_cache.h"
#include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/utils.h" #include "video_core/renderer_opengl/utils.h"
#include "video_core/shader/glsl_decompiler.h"
#include "video_core/shader/shader_ir.h"
namespace OpenGL { namespace OpenGL {
using VideoCommon::Shader::ProgramCode;
/// Gets the address for the specified shader stage program /// Gets the address for the specified shader stage program
static VAddr GetShaderAddress(Maxwell::ShaderProgram program) { static VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
@ -24,8 +28,8 @@ static VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
} }
/// Gets the shader program code from memory for the specified address /// Gets the shader program code from memory for the specified address
static GLShader::ProgramCode GetShaderCode(VAddr addr) { static ProgramCode GetShaderCode(VAddr addr) {
GLShader::ProgramCode program_code(GLShader::MAX_PROGRAM_CODE_LENGTH); ProgramCode program_code(VideoCommon::Shader::MAX_PROGRAM_LENGTH);
Memory::ReadBlock(addr, program_code.data(), program_code.size() * sizeof(u64)); Memory::ReadBlock(addr, program_code.data(), program_code.size() * sizeof(u64));
return program_code; return program_code;
} }

View File

@ -13,6 +13,7 @@
#include "video_core/rasterizer_cache.h" #include "video_core/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_gen.h" #include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/shader/glsl_decompiler.h"
namespace OpenGL { namespace OpenGL {

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <functional>
#include <optional>
#include <string>
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
namespace OpenGL::GLShader::Decompiler {
using Tegra::Engines::Maxwell3D;
std::string GetCommonDeclarations();
std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
Maxwell3D::Regs::ShaderStage stage,
const std::string& suffix);
} // namespace OpenGL::GLShader::Decompiler

View File

@ -5,24 +5,27 @@
#include <fmt/format.h> #include <fmt/format.h>
#include "common/assert.h" #include "common/assert.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_opengl/gl_shader_gen.h" #include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/shader/glsl_decompiler.h"
#include "video_core/shader/shader_ir.h"
namespace OpenGL::GLShader { namespace OpenGL::GLShader {
using Tegra::Engines::Maxwell3D; using Tegra::Engines::Maxwell3D;
using VideoCommon::Shader::ProgramCode;
using VideoCommon::Shader::ShaderIR;
static constexpr u32 PROGRAM_OFFSET{10}; static constexpr u32 PROGRAM_OFFSET{10};
ProgramResult GenerateVertexShader(const ShaderSetup& setup) { ProgramResult GenerateVertexShader(const ShaderSetup& setup) {
std::string out = "#version 430 core\n";
out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
out += "// Shader Unique Id: VS" + id + "\n\n";
out += Decompiler::GetCommonDeclarations(); std::string out = "#version 430 core\n";
out += "// Shader Unique Id: VS" + id + '\n';
out += "#extension GL_ARB_separate_shader_objects : enable\n";
out += GetCommonDeclarations();
out += R"( out += R"(
layout (location = 0) out vec4 position; layout (location = 0) out vec4 position;
layout(std140) uniform vs_config { layout(std140) uniform vs_config {
@ -31,39 +34,30 @@ layout(std140) uniform vs_config {
uvec4 alpha_test; uvec4 alpha_test;
}; };
)"; )";
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
if (setup.IsDualProgram()) { ProgramResult program = Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
out += "bool exec_vertex_b();\n";
}
ProgramResult program =
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
Maxwell3D::Regs::ShaderStage::Vertex, "vertex")
.value_or(ProgramResult());
out += program.first; out += program.first;
if (setup.IsDualProgram()) { if (setup.IsDualProgram()) {
ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
ProgramResult program_b = ProgramResult program_b =
Decompiler::DecompileProgram(setup.program.code_b, PROGRAM_OFFSET, Decompile(program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b")
.value_or(ProgramResult());
out += program_b.first; out += program_b.first;
} }
out += R"( out += R"(
void main() { void main() {
position = vec4(0.0, 0.0, 0.0, 0.0); position = vec4(0.0, 0.0, 0.0, 0.0);
exec_vertex(); execute_vertex();
)"; )";
if (setup.IsDualProgram()) { if (setup.IsDualProgram()) {
out += " exec_vertex_b();"; out += " execute_vertex_b();";
} }
out += R"( out += R"(
// Check if the flip stage is VertexB // Check if the flip stage is VertexB
// Config pack's second value is flip_stage // Config pack's second value is flip_stage
if (config_pack[1] == 1) { if (config_pack[1] == 1) {
@ -77,25 +71,23 @@ void main() {
if (config_pack[1] == 1) { if (config_pack[1] == 1) {
position.w = 1.0; position.w = 1.0;
} }
} })";
)";
return {out, program.second}; return {out, program.second};
} }
ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
// Version is intentionally skipped in shader generation, it's added by the lazy compilation. // Version is intentionally skipped in shader generation, it's added by the lazy compilation.
std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
out += "// Shader Unique Id: GS" + id + "\n\n";
out += Decompiler::GetCommonDeclarations();
out += "bool exec_geometry();\n";
std::string out = out += "// Shader Unique Id: GS" + id + '\n';
out += "#extension GL_ARB_separate_shader_objects : enable\n";
out += GetCommonDeclarations();
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program = ProgramResult program =
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET, Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
Maxwell3D::Regs::ShaderStage::Geometry, "geometry")
.value_or(ProgramResult());
out += R"( out += R"(
out gl_PerVertex { out gl_PerVertex {
vec4 gl_Position; vec4 gl_Position;
@ -109,28 +101,26 @@ layout (std140) uniform gs_config {
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
uvec4 alpha_test; uvec4 alpha_test;
}; };
void main() {
exec_geometry();
}
)"; )";
out += program.first; out += program.first;
out = R"(
void main() {
execute_geometry();
};)";
return {out, program.second}; return {out, program.second};
} }
ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
std::string out = "#version 430 core\n";
out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
out += "// Shader Unique Id: FS" + id + "\n\n";
out += Decompiler::GetCommonDeclarations();
out += "bool exec_fragment();\n";
ProgramResult program = std::string out = "#version 430 core\n";
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET, out += "// Shader Unique Id: FS" + id + '\n';
Maxwell3D::Regs::ShaderStage::Fragment, "fragment") out += "#extension GL_ARB_separate_shader_objects : enable\n";
.value_or(ProgramResult()); out += GetCommonDeclarations();
out += R"( out += R"(
layout(location = 0) out vec4 FragColor0; layout(location = 0) out vec4 FragColor0;
layout(location = 1) out vec4 FragColor1; layout(location = 1) out vec4 FragColor1;
@ -171,14 +161,20 @@ bool AlphaFunc(in float value) {
default: default:
return false; return false;
} }
} })";
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
ProgramResult program =
Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
out += program.first;
out += R"(
void main() { void main() {
exec_fragment(); execute_fragment();
} }
)"; )";
out += program.first;
return {out, program.second}; return {out, program.second};
} }
} // namespace OpenGL::GLShader } // namespace OpenGL::GLShader

View File

@ -10,164 +10,12 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "video_core/engines/shader_bytecode.h" #include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/glsl_decompiler.h"
#include "video_core/shader/shader_ir.h"
namespace OpenGL::GLShader { namespace OpenGL::GLShader {
constexpr std::size_t MAX_PROGRAM_CODE_LENGTH{0x1000}; using VideoCommon::Shader::ProgramCode;
using ProgramCode = std::vector<u64>;
enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
class ConstBufferEntry {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
public:
void MarkAsUsed(u64 index, u64 offset, Maxwell::ShaderStage stage) {
is_used = true;
this->index = static_cast<unsigned>(index);
this->stage = stage;
max_offset = std::max(max_offset, static_cast<unsigned>(offset));
}
void MarkAsUsedIndirect(u64 index, Maxwell::ShaderStage stage) {
is_used = true;
is_indirect = true;
this->index = static_cast<unsigned>(index);
this->stage = stage;
}
bool IsUsed() const {
return is_used;
}
bool IsIndirect() const {
return is_indirect;
}
unsigned GetIndex() const {
return index;
}
unsigned GetSize() const {
return max_offset + 1;
}
std::string GetName() const {
return BufferBaseNames[static_cast<std::size_t>(stage)] + std::to_string(index);
}
u32 GetHash() const {
return (static_cast<u32>(stage) << 16) | index;
}
private:
static constexpr std::array<const char*, Maxwell::MaxShaderStage> BufferBaseNames = {
"buffer_vs_c", "buffer_tessc_c", "buffer_tesse_c", "buffer_gs_c", "buffer_fs_c",
};
bool is_used{};
bool is_indirect{};
unsigned index{};
unsigned max_offset{};
Maxwell::ShaderStage stage;
};
class SamplerEntry {
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
public:
SamplerEntry(Maxwell::ShaderStage stage, std::size_t offset, std::size_t index,
Tegra::Shader::TextureType type, bool is_array, bool is_shadow)
: offset(offset), stage(stage), sampler_index(index), type(type), is_array(is_array),
is_shadow(is_shadow) {}
std::size_t GetOffset() const {
return offset;
}
std::size_t GetIndex() const {
return sampler_index;
}
Maxwell::ShaderStage GetStage() const {
return stage;
}
std::string GetName() const {
return std::string(TextureSamplerNames[static_cast<std::size_t>(stage)]) + '_' +
std::to_string(sampler_index);
}
std::string GetTypeString() const {
using Tegra::Shader::TextureType;
std::string glsl_type;
switch (type) {
case TextureType::Texture1D:
glsl_type = "sampler1D";
break;
case TextureType::Texture2D:
glsl_type = "sampler2D";
break;
case TextureType::Texture3D:
glsl_type = "sampler3D";
break;
case TextureType::TextureCube:
glsl_type = "samplerCube";
break;
default:
UNIMPLEMENTED();
}
if (is_array)
glsl_type += "Array";
if (is_shadow)
glsl_type += "Shadow";
return glsl_type;
}
Tegra::Shader::TextureType GetType() const {
return type;
}
bool IsArray() const {
return is_array;
}
bool IsShadow() const {
return is_shadow;
}
u32 GetHash() const {
return (static_cast<u32>(stage) << 16) | static_cast<u32>(sampler_index);
}
static std::string GetArrayName(Maxwell::ShaderStage stage) {
return TextureSamplerNames[static_cast<std::size_t>(stage)];
}
private:
static constexpr std::array<const char*, Maxwell::MaxShaderStage> TextureSamplerNames = {
"tex_vs", "tex_tessc", "tex_tesse", "tex_gs", "tex_fs",
};
/// Offset in TSC memory from which to read the sampler object, as specified by the sampling
/// instruction.
std::size_t offset;
Maxwell::ShaderStage stage; ///< Shader stage where this sampler was used.
std::size_t sampler_index; ///< Value used to index into the generated GLSL sampler array.
Tegra::Shader::TextureType type; ///< The type used to sample this texture (Texture2D, etc)
bool is_array; ///< Whether the texture is being sampled as an array texture or not.
bool is_shadow; ///< Whether the texture is being sampled as a depth texture or not.
};
struct ShaderEntries {
std::vector<ConstBufferEntry> const_buffer_entries;
std::vector<SamplerEntry> texture_samplers;
std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> clip_distances;
std::size_t shader_length;
};
using ProgramResult = std::pair<std::string, ShaderEntries>;
struct ShaderSetup { struct ShaderSetup {
explicit ShaderSetup(ProgramCode program_code) { explicit ShaderSetup(ProgramCode program_code) {