diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 112 |
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 |
| 21 | constexpr u32 ReservedUniformBlocks = 1; | 23 | constexpr u32 ReservedUniformBlocks = 1; |
| 22 | 24 | ||
| 25 | constexpr u32 NumStages = 5; | ||
| 26 | |||
| 27 | constexpr 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 | |||
| 31 | constexpr 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 | |||
| 36 | constexpr 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 | |||
| 41 | constexpr 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 | |||
| 23 | template <typename T> | 46 | template <typename T> |
| 24 | T GetInteger(GLenum pname) { | 47 | T 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 | ||
| 54 | constexpr Device::BaseBindings operator+(Device::BaseBindings lhs, Device::BaseBindings rhs) { | 77 | u32 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 | ||
| 60 | Device::BaseBindings BuildBaseBindings(GLenum uniform_blocks, GLenum shader_storage_blocks, | 86 | std::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 | ||
| 72 | Device::Device() { | 135 | Device::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); |