summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.h1
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_device.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp91
4 files changed, 88 insertions, 27 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 85d309d9b..b1e640dd1 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -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;
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index b6d9e0ddb..38497678a 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -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;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 78ff5ee58..de8490682 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -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{};
};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 33c0edca9..8df91a4c6 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -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;