summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp112
1 files changed, 76 insertions, 36 deletions
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 3adf57c96..a95bd4b2c 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -5,7 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <array> 6#include <array>
7#include <cstddef> 7#include <cstddef>
8#include <optional>
8#include <vector> 9#include <vector>
10
9#include <glad/glad.h> 11#include <glad/glad.h>
10 12
11#include "common/logging/log.h" 13#include "common/logging/log.h"
@@ -20,6 +22,27 @@ namespace {
20// One uniform block is reserved for emulation purposes 22// One uniform block is reserved for emulation purposes
21constexpr u32 ReservedUniformBlocks = 1; 23constexpr u32 ReservedUniformBlocks = 1;
22 24
25constexpr u32 NumStages = 5;
26
27constexpr std::array LimitUBOs = {GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
28 GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
29 GL_MAX_GEOMETRY_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS};
30
31constexpr std::array LimitSSBOs = {
32 GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
33 GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
34 GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS};
35
36constexpr std::array LimitSamplers = {
37 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
38 GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS,
39 GL_MAX_TEXTURE_IMAGE_UNITS};
40
41constexpr std::array LimitImages = {GL_MAX_VERTEX_IMAGE_UNIFORMS,
42 GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
43 GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,
44 GL_MAX_GEOMETRY_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS};
45
23template <typename T> 46template <typename T>
24T GetInteger(GLenum pname) { 47T GetInteger(GLenum pname) {
25 GLint temporary; 48 GLint temporary;
@@ -51,54 +74,71 @@ bool HasExtension(const std::vector<std::string_view>& images, std::string_view
51 return std::find(images.begin(), images.end(), extension) != images.end(); 74 return std::find(images.begin(), images.end(), extension) != images.end();
52} 75}
53 76
54constexpr Device::BaseBindings operator+(Device::BaseBindings lhs, Device::BaseBindings rhs) { 77u32 Extract(u32& base, u32& num, u32 amount, std::optional<GLenum> limit = {}) {
55 return Device::BaseBindings{lhs.uniform_buffer + rhs.uniform_buffer, 78 ASSERT(num >= amount);
56 lhs.shader_storage_buffer + rhs.shader_storage_buffer, 79 if (limit) {
57 lhs.sampler + rhs.sampler, lhs.image + rhs.image}; 80 amount = std::min(amount, GetInteger<u32>(*limit));
81 }
82 num -= amount;
83 return std::exchange(base, base + amount);
58} 84}
59 85
60Device::BaseBindings BuildBaseBindings(GLenum uniform_blocks, GLenum shader_storage_blocks, 86std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> BuildBaseBindings() noexcept {
61 GLenum texture_image_units, GLenum image_uniforms) noexcept { 87 std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> bindings;
62 return Device::BaseBindings{ 88
63 GetInteger<u32>(uniform_blocks) - ReservedUniformBlocks, 89 static std::array<std::size_t, 5> stage_swizzle = {0, 1, 2, 3, 4};
64 GetInteger<u32>(shader_storage_blocks), 90 const u32 total_ubos = GetInteger<u32>(GL_MAX_UNIFORM_BUFFER_BINDINGS);
65 GetInteger<u32>(texture_image_units), 91 const u32 total_ssbos = GetInteger<u32>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
66 GetInteger<u32>(image_uniforms), 92 const u32 total_samplers = GetInteger<u32>(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
67 }; 93
94 u32 num_ubos = total_ubos - ReservedUniformBlocks;
95 u32 num_ssbos = total_ssbos;
96 u32 num_samplers = total_samplers;
97
98 u32 base_ubo = ReservedUniformBlocks;
99 u32 base_ssbo = 0;
100 u32 base_samplers = 0;
101
102 for (std::size_t i = 0; i < NumStages; ++i) {
103 const std::size_t stage = stage_swizzle[i];
104 bindings[stage] = {
105 Extract(base_ubo, num_ubos, total_ubos / NumStages, LimitUBOs[stage]),
106 Extract(base_ssbo, num_ssbos, total_ssbos / NumStages, LimitSSBOs[stage]),
107 Extract(base_samplers, num_samplers, total_samplers / NumStages, LimitSamplers[stage])};
108 }
109
110 u32 num_images = GetInteger<u32>(GL_MAX_IMAGE_UNITS);
111 u32 base_images = 0;
112
113 // Reserve more image bindings on fragment and vertex stages.
114 bindings[4].image =
115 Extract(base_images, num_images, num_images / NumStages + 2, LimitImages[4]);
116 bindings[0].image =
117 Extract(base_images, num_images, num_images / NumStages + 1, LimitImages[0]);
118
119 // Reserve the other image bindings.
120 const u32 total_extracted_images = num_images / (NumStages - 2);
121 for (std::size_t i = 2; i < NumStages; ++i) {
122 const std::size_t stage = stage_swizzle[i];
123 bindings[stage].image =
124 Extract(base_images, num_images, total_extracted_images, LimitImages[stage]);
125 }
126
127 // Compute doesn't care about any of this.
128 bindings[5] = {0, 0, 0, 0};
129
130 return bindings;
68} 131}
69 132
70} // Anonymous namespace 133} // Anonymous namespace
71 134
72Device::Device() { 135Device::Device() : base_bindings{BuildBaseBindings()} {
73 const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); 136 const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
74 const std::vector extensions = GetExtensions(); 137 const std::vector extensions = GetExtensions();
75 138
76 const bool is_nvidia = vendor == "NVIDIA Corporation"; 139 const bool is_nvidia = vendor == "NVIDIA Corporation";
77 const bool is_intel = vendor == "Intel"; 140 const bool is_intel = vendor == "Intel";
78 141
79 // Reserve the first UBO for emulation bindings
80 base_bindings[0] = BaseBindings{ReservedUniformBlocks, 0, 0, 0};
81 base_bindings[1] = base_bindings[0] + BuildBaseBindings(GL_MAX_VERTEX_UNIFORM_BLOCKS,
82 GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
83 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
84 GL_MAX_VERTEX_IMAGE_UNIFORMS);
85 base_bindings[2] =
86 base_bindings[1] + BuildBaseBindings(GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
87 GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
88 GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
89 GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS);
90 base_bindings[3] =
91 base_bindings[2] + BuildBaseBindings(GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
92 GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
93 GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
94 GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS);
95 base_bindings[4] = base_bindings[3] + BuildBaseBindings(GL_MAX_GEOMETRY_UNIFORM_BLOCKS,
96 GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
97 GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS,
98 GL_MAX_GEOMETRY_IMAGE_UNIFORMS);
99 // Compute doesn't need any of that
100 base_bindings[5] = BaseBindings{0, 0, 0, 0};
101
102 uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); 142 uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
103 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); 143 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
104 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 144 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);