mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-24 20:36:24 -05:00
video_core: Replace gl_shader_decompiler
This commit is contained in:
parent
0c6fb456e0
commit
a4f052f6b3
8 changed files with 58 additions and 4186 deletions
|
@ -42,8 +42,6 @@ add_library(video_core STATIC
|
|||
renderer_opengl/gl_resource_manager.h
|
||||
renderer_opengl/gl_shader_cache.cpp
|
||||
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.h
|
||||
renderer_opengl/gl_shader_manager.cpp
|
||||
|
|
|
@ -925,7 +925,7 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
|
|||
const auto& gpu = Core::System::GetInstance().GPU();
|
||||
const auto& maxwell3d = gpu.Maxwell3D();
|
||||
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;
|
||||
std::array<GLuint, max_binds> bind_buffers;
|
||||
|
@ -993,7 +993,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
|||
MICROPROFILE_SCOPE(OpenGL_Texture);
|
||||
const auto& gpu = Core::System::GetInstance().GPU();
|
||||
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),
|
||||
"Exceeded the number of active textures.");
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
#include "video_core/renderer_opengl/gl_shader_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||
#include "video_core/renderer_opengl/utils.h"
|
||||
#include "video_core/shader/glsl_decompiler.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
using VideoCommon::Shader::ProgramCode;
|
||||
|
||||
/// Gets the address for the specified shader stage program
|
||||
static VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
|
||||
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
|
||||
static GLShader::ProgramCode GetShaderCode(VAddr addr) {
|
||||
GLShader::ProgramCode program_code(GLShader::MAX_PROGRAM_CODE_LENGTH);
|
||||
static ProgramCode GetShaderCode(VAddr addr) {
|
||||
ProgramCode program_code(VideoCommon::Shader::MAX_PROGRAM_LENGTH);
|
||||
Memory::ReadBlock(addr, program_code.data(), program_code.size() * sizeof(u64));
|
||||
return program_code;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "video_core/rasterizer_cache.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||
#include "video_core/shader/glsl_decompiler.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
@ -5,24 +5,27 @@
|
|||
#include <fmt/format.h>
|
||||
#include "common/assert.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/shader/glsl_decompiler.h"
|
||||
#include "video_core/shader/shader_ir.h"
|
||||
|
||||
namespace OpenGL::GLShader {
|
||||
|
||||
using Tegra::Engines::Maxwell3D;
|
||||
using VideoCommon::Shader::ProgramCode;
|
||||
using VideoCommon::Shader::ShaderIR;
|
||||
|
||||
static constexpr u32 PROGRAM_OFFSET{10};
|
||||
|
||||
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);
|
||||
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"(
|
||||
|
||||
layout (location = 0) out vec4 position;
|
||||
|
||||
layout(std140) uniform vs_config {
|
||||
|
@ -31,39 +34,30 @@ layout(std140) uniform vs_config {
|
|||
uvec4 alpha_test;
|
||||
};
|
||||
)";
|
||||
|
||||
if (setup.IsDualProgram()) {
|
||||
out += "bool exec_vertex_b();\n";
|
||||
}
|
||||
|
||||
ProgramResult program =
|
||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||
Maxwell3D::Regs::ShaderStage::Vertex, "vertex")
|
||||
.value_or(ProgramResult());
|
||||
ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
|
||||
ProgramResult program = Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
|
||||
|
||||
out += program.first;
|
||||
|
||||
if (setup.IsDualProgram()) {
|
||||
ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
|
||||
ProgramResult program_b =
|
||||
Decompiler::DecompileProgram(setup.program.code_b, PROGRAM_OFFSET,
|
||||
Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b")
|
||||
.value_or(ProgramResult());
|
||||
Decompile(program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
|
||||
|
||||
out += program_b.first;
|
||||
}
|
||||
|
||||
out += R"(
|
||||
|
||||
void main() {
|
||||
position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
exec_vertex();
|
||||
execute_vertex();
|
||||
)";
|
||||
|
||||
if (setup.IsDualProgram()) {
|
||||
out += " exec_vertex_b();";
|
||||
out += " execute_vertex_b();";
|
||||
}
|
||||
|
||||
out += R"(
|
||||
|
||||
// Check if the flip stage is VertexB
|
||||
// Config pack's second value is flip_stage
|
||||
if (config_pack[1] == 1) {
|
||||
|
@ -77,25 +71,23 @@ void main() {
|
|||
if (config_pack[1] == 1) {
|
||||
position.w = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
)";
|
||||
})";
|
||||
|
||||
return {out, program.second};
|
||||
}
|
||||
|
||||
ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
|
||||
// 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);
|
||||
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 =
|
||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||
Maxwell3D::Regs::ShaderStage::Geometry, "geometry")
|
||||
.value_or(ProgramResult());
|
||||
Decompile(program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
|
||||
|
||||
out += R"(
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
|
@ -109,28 +101,26 @@ layout (std140) uniform gs_config {
|
|||
uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
|
||||
uvec4 alpha_test;
|
||||
};
|
||||
|
||||
void main() {
|
||||
exec_geometry();
|
||||
}
|
||||
|
||||
)";
|
||||
|
||||
out += program.first;
|
||||
|
||||
out = R"(
|
||||
void main() {
|
||||
execute_geometry();
|
||||
};)";
|
||||
|
||||
return {out, program.second};
|
||||
}
|
||||
|
||||
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);
|
||||
out += "// Shader Unique Id: FS" + id + "\n\n";
|
||||
out += Decompiler::GetCommonDeclarations();
|
||||
out += "bool exec_fragment();\n";
|
||||
|
||||
ProgramResult program =
|
||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||
Maxwell3D::Regs::ShaderStage::Fragment, "fragment")
|
||||
.value_or(ProgramResult());
|
||||
std::string out = "#version 430 core\n";
|
||||
out += "// Shader Unique Id: FS" + id + '\n';
|
||||
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||
out += GetCommonDeclarations();
|
||||
|
||||
out += R"(
|
||||
layout(location = 0) out vec4 FragColor0;
|
||||
layout(location = 1) out vec4 FragColor1;
|
||||
|
@ -171,14 +161,20 @@ bool AlphaFunc(in float value) {
|
|||
default:
|
||||
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() {
|
||||
exec_fragment();
|
||||
execute_fragment();
|
||||
}
|
||||
|
||||
)";
|
||||
out += program.first;
|
||||
return {out, program.second};
|
||||
}
|
||||
} // namespace OpenGL::GLShader
|
||||
} // namespace OpenGL::GLShader
|
|
@ -10,164 +10,12 @@
|
|||
|
||||
#include "common/common_types.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 {
|
||||
|
||||
constexpr std::size_t MAX_PROGRAM_CODE_LENGTH{0x1000};
|
||||
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>;
|
||||
using VideoCommon::Shader::ProgramCode;
|
||||
|
||||
struct ShaderSetup {
|
||||
explicit ShaderSetup(ProgramCode program_code) {
|
||||
|
|
Loading…
Reference in a new issue