gl_shader_decompiler: Declare all possible varyings on physical attribute usage

merge-requests/60/head
ReinUsesLisp 2019-04-30 00:09:51 +07:00
parent 06b363c9b5
commit bd81a03d9d
4 changed files with 88 additions and 27 deletions

@ -51,6 +51,7 @@ public:
static constexpr std::size_t NumCBData = 16;
static constexpr std::size_t NumVertexArrays = 32;
static constexpr std::size_t NumVertexAttributes = 32;
static constexpr std::size_t NumVaryings = 31;
static constexpr std::size_t NumTextureSamplers = 32;
static constexpr std::size_t NumClipDistances = 8;
static constexpr std::size_t MaxShaderProgram = 6;

@ -21,9 +21,18 @@ T GetInteger(GLenum pname) {
Device::Device() {
uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
has_variable_aoffi = TestVariableAoffi();
}
Device::Device(std::nullptr_t) {
uniform_buffer_alignment = 0;
max_vertex_attributes = 16;
max_varyings = 15;
has_variable_aoffi = true;
}
bool Device::TestVariableAoffi() {
const GLchar* AOFFI_TEST = R"(#version 430 core
uniform sampler2D tex;

@ -5,17 +5,27 @@
#pragma once
#include <cstddef>
#include "common/common_types.h"
namespace OpenGL {
class Device {
public:
Device();
explicit Device();
explicit Device(std::nullptr_t);
std::size_t GetUniformBufferAlignment() const {
return uniform_buffer_alignment;
}
u32 GetMaxVertexAttributes() const {
return max_vertex_attributes;
}
u32 GetMaxVaryings() const {
return max_varyings;
}
bool HasVariableAoffi() const {
return has_variable_aoffi;
}
@ -24,6 +34,8 @@ private:
static bool TestVariableAoffi();
std::size_t uniform_buffer_alignment{};
u32 max_vertex_attributes{};
u32 max_varyings{};
bool has_variable_aoffi{};
};

@ -316,55 +316,85 @@ private:
}
void DeclareInputAttributes() {
if (ir.HasPhysicalAttributes()) {
const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes()
: GetNumPhysicalVaryings()};
for (u32 i = 0; i < num_inputs; ++i) {
constexpr auto generic_base{static_cast<u32>(Attribute::Index::Attribute_0)};
const auto index{static_cast<Attribute::Index>(generic_base + i)};
DeclareInputAttribute(index);
}
code.AddNewLine();
return;
}
const auto& attributes = ir.GetInputAttributes();
for (const auto index : attributes) {
if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
// Skip when it's not a generic attribute
continue;
}
// TODO(bunnei): Use proper number of elements for these
u32 idx = static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
if (stage != ShaderStage::Vertex) {
// If inputs are varyings, add an offset
idx += GENERIC_VARYING_START_LOCATION;
}
std::string attr = GetInputAttribute(index);
if (stage == ShaderStage::Geometry) {
attr = "gs_" + attr + "[]";
}
std::string suffix;
if (stage == ShaderStage::Fragment) {
const auto input_mode =
header.ps.GetAttributeUse(idx - GENERIC_VARYING_START_LOCATION);
suffix = GetInputFlags(input_mode);
}
code.AddLine("layout (location = " + std::to_string(idx) + ") " + suffix + "in vec4 " +
attr + ';');
DeclareInputAttribute(index);
}
if (!attributes.empty())
code.AddNewLine();
}
void DeclareInputAttribute(Attribute::Index index) {
const u32 generic_index{static_cast<u32>(index) -
static_cast<u32>(Attribute::Index::Attribute_0)};
std::string name{GetInputAttribute(index)};
if (stage == ShaderStage::Geometry) {
name = "gs_" + name + "[]";
}
std::string suffix;
if (stage == ShaderStage::Fragment) {
const auto input_mode{header.ps.GetAttributeUse(generic_index)};
suffix = GetInputFlags(input_mode);
}
u32 location = generic_index;
if (stage != ShaderStage::Vertex) {
// If inputs are varyings, add an offset
location += GENERIC_VARYING_START_LOCATION;
}
code.AddLine("layout (location = " + std::to_string(location) + ") " + suffix + "in vec4 " +
name + ';');
}
void DeclareOutputAttributes() {
if (ir.HasPhysicalAttributes()) {
for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) {
constexpr auto generic_base{static_cast<u32>(Attribute::Index::Attribute_0)};
const auto index{static_cast<Attribute::Index>(generic_base + i)};
DeclareOutputAttribute(index);
}
code.AddNewLine();
return;
}
const auto& attributes = ir.GetOutputAttributes();
for (const auto index : attributes) {
if (index < Attribute::Index::Attribute_0 || index > Attribute::Index::Attribute_31) {
// Skip when it's not a generic attribute
continue;
}
// TODO(bunnei): Use proper number of elements for these
const auto idx = static_cast<u32>(index) -
static_cast<u32>(Attribute::Index::Attribute_0) +
GENERIC_VARYING_START_LOCATION;
code.AddLine("layout (location = " + std::to_string(idx) + ") out vec4 " +
GetOutputAttribute(index) + ';');
DeclareOutputAttribute(index);
}
if (!attributes.empty())
code.AddNewLine();
}
void DeclareOutputAttribute(Attribute::Index index) {
const auto location{static_cast<u32>(index) -
static_cast<u32>(Attribute::Index::Attribute_0) +
GENERIC_VARYING_START_LOCATION};
code.AddLine("layout (location = " + std::to_string(location) + ") out vec4 " +
GetOutputAttribute(index) + ';');
}
void DeclareConstantBuffers() {
for (const auto& entry : ir.GetConstantBuffers()) {
const auto [index, size] = entry;
@ -1650,6 +1680,15 @@ private:
return name + '_' + std::to_string(index) + '_' + suffix;
}
u32 GetNumPhysicalAttributes() const {
return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes);
}
u32 GetNumPhysicalVaryings() const {
return std::min<u32>(device.GetMaxVaryings() - GENERIC_VARYING_START_LOCATION,
Maxwell::NumVaryings);
}
const Device& device;
const ShaderIR& ir;
const ShaderStage stage;