summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/stream.cpp4
-rw-r--r--src/video_core/engines/maxwell_3d.cpp16
-rw-r--r--src/video_core/engines/maxwell_3d.h37
-rw-r--r--src/video_core/memory_manager.cpp75
-rw-r--r--src/video_core/memory_manager.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp118
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.cpp42
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp252
-rw-r--r--src/video_core/renderer_opengl/gl_state.h60
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp5
12 files changed, 443 insertions, 190 deletions
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 742a5e0a0..f35628e45 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -11,7 +11,6 @@
11#include "audio_core/stream.h" 11#include "audio_core/stream.h"
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/microprofile.h"
15#include "core/core_timing.h" 14#include "core/core_timing.h"
16#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
17#include "core/settings.h" 16#include "core/settings.h"
@@ -104,10 +103,7 @@ void Stream::PlayNextBuffer() {
104 CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {}); 103 CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {});
105} 104}
106 105
107MICROPROFILE_DEFINE(AudioOutput, "Audio", "ReleaseActiveBuffer", MP_RGB(100, 100, 255));
108
109void Stream::ReleaseActiveBuffer() { 106void Stream::ReleaseActiveBuffer() {
110 MICROPROFILE_SCOPE(AudioOutput);
111 ASSERT(active_buffer); 107 ASSERT(active_buffer);
112 released_buffers.push(std::move(active_buffer)); 108 released_buffers.push(std::move(active_buffer));
113 release_callback(); 109 release_callback();
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d79c50919..2cd595f26 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -37,6 +37,22 @@ void Maxwell3D::InitializeRegisterDefaults() {
37 regs.viewport[viewport].depth_range_near = 0.0f; 37 regs.viewport[viewport].depth_range_near = 0.0f;
38 regs.viewport[viewport].depth_range_far = 1.0f; 38 regs.viewport[viewport].depth_range_far = 1.0f;
39 } 39 }
40 // Doom and Bomberman seems to use the uninitialized registers and just enable blend
41 // so initialize blend registers with sane values
42 regs.blend.equation_rgb = Regs::Blend::Equation::Add;
43 regs.blend.factor_source_rgb = Regs::Blend::Factor::One;
44 regs.blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
45 regs.blend.equation_a = Regs::Blend::Equation::Add;
46 regs.blend.factor_source_a = Regs::Blend::Factor::One;
47 regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
48 for (std::size_t blend_index = 0; blend_index < Regs::NumRenderTargets; blend_index++) {
49 regs.independent_blend[blend_index].equation_rgb = Regs::Blend::Equation::Add;
50 regs.independent_blend[blend_index].factor_source_rgb = Regs::Blend::Factor::One;
51 regs.independent_blend[blend_index].factor_dest_rgb = Regs::Blend::Factor::Zero;
52 regs.independent_blend[blend_index].equation_a = Regs::Blend::Equation::Add;
53 regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
54 regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
55 }
40} 56}
41 57
42void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { 58void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 50873813e..0509ba3a2 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -462,6 +462,16 @@ public:
462 } 462 }
463 }; 463 };
464 464
465 struct ColorMask {
466 union {
467 u32 raw;
468 BitField<0, 4, u32> R;
469 BitField<4, 4, u32> G;
470 BitField<8, 4, u32> B;
471 BitField<12, 4, u32> A;
472 };
473 };
474
465 bool IsShaderConfigEnabled(std::size_t index) const { 475 bool IsShaderConfigEnabled(std::size_t index) const {
466 // The VertexB is always enabled. 476 // The VertexB is always enabled.
467 if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) { 477 if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) {
@@ -571,7 +581,11 @@ public:
571 u32 stencil_back_mask; 581 u32 stencil_back_mask;
572 u32 stencil_back_func_mask; 582 u32 stencil_back_func_mask;
573 583
574 INSERT_PADDING_WORDS(0x13); 584 INSERT_PADDING_WORDS(0xC);
585
586 u32 color_mask_common;
587
588 INSERT_PADDING_WORDS(0x6);
575 589
576 u32 rt_separate_frag_data; 590 u32 rt_separate_frag_data;
577 591
@@ -646,8 +660,14 @@ public:
646 ComparisonOp depth_test_func; 660 ComparisonOp depth_test_func;
647 float alpha_test_ref; 661 float alpha_test_ref;
648 ComparisonOp alpha_test_func; 662 ComparisonOp alpha_test_func;
649 663 u32 draw_tfb_stride;
650 INSERT_PADDING_WORDS(0x9); 664 struct {
665 float r;
666 float g;
667 float b;
668 float a;
669 } blend_color;
670 INSERT_PADDING_WORDS(0x4);
651 671
652 struct { 672 struct {
653 u32 separate_alpha; 673 u32 separate_alpha;
@@ -841,8 +861,9 @@ public:
841 BitField<6, 4, u32> RT; 861 BitField<6, 4, u32> RT;
842 BitField<10, 11, u32> layer; 862 BitField<10, 11, u32> layer;
843 } clear_buffers; 863 } clear_buffers;
844 864 INSERT_PADDING_WORDS(0xB);
845 INSERT_PADDING_WORDS(0x4B); 865 std::array<ColorMask, NumRenderTargets> color_mask;
866 INSERT_PADDING_WORDS(0x38);
846 867
847 struct { 868 struct {
848 u32 query_address_high; 869 u32 query_address_high;
@@ -1075,6 +1096,7 @@ ASSERT_REG_POSITION(scissor_test, 0x380);
1075ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5); 1096ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
1076ASSERT_REG_POSITION(stencil_back_mask, 0x3D6); 1097ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
1077ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7); 1098ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
1099ASSERT_REG_POSITION(color_mask_common, 0x3E4);
1078ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); 1100ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
1079ASSERT_REG_POSITION(zeta, 0x3F8); 1101ASSERT_REG_POSITION(zeta, 0x3F8);
1080ASSERT_REG_POSITION(vertex_attrib_format, 0x458); 1102ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
@@ -1087,6 +1109,10 @@ ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);
1087ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB); 1109ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB);
1088ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2); 1110ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
1089ASSERT_REG_POSITION(depth_test_func, 0x4C3); 1111ASSERT_REG_POSITION(depth_test_func, 0x4C3);
1112ASSERT_REG_POSITION(alpha_test_ref, 0x4C4);
1113ASSERT_REG_POSITION(alpha_test_func, 0x4C5);
1114ASSERT_REG_POSITION(draw_tfb_stride, 0x4C6);
1115ASSERT_REG_POSITION(blend_color, 0x4C7);
1090ASSERT_REG_POSITION(blend, 0x4CF); 1116ASSERT_REG_POSITION(blend, 0x4CF);
1091ASSERT_REG_POSITION(stencil_enable, 0x4E0); 1117ASSERT_REG_POSITION(stencil_enable, 0x4E0);
1092ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1); 1118ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1);
@@ -1117,6 +1143,7 @@ ASSERT_REG_POSITION(instanced_arrays, 0x620);
1117ASSERT_REG_POSITION(cull, 0x646); 1143ASSERT_REG_POSITION(cull, 0x646);
1118ASSERT_REG_POSITION(logic_op, 0x671); 1144ASSERT_REG_POSITION(logic_op, 0x671);
1119ASSERT_REG_POSITION(clear_buffers, 0x674); 1145ASSERT_REG_POSITION(clear_buffers, 0x674);
1146ASSERT_REG_POSITION(color_mask, 0x680);
1120ASSERT_REG_POSITION(query, 0x6C0); 1147ASSERT_REG_POSITION(query, 0x6C0);
1121ASSERT_REG_POSITION(vertex_array[0], 0x700); 1148ASSERT_REG_POSITION(vertex_array[0], 0x700);
1122ASSERT_REG_POSITION(independent_blend, 0x780); 1149ASSERT_REG_POSITION(independent_blend, 0x780);
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 90a8e825d..77a20bb84 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -4,18 +4,21 @@
4 4
5#include "common/alignment.h" 5#include "common/alignment.h"
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h"
7#include "video_core/memory_manager.h" 8#include "video_core/memory_manager.h"
8 9
9namespace Tegra { 10namespace Tegra {
10 11
11GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) { 12GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
12 std::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, align); 13 const std::optional<GPUVAddr> gpu_addr{FindFreeBlock(0, size, align, PageStatus::Unmapped)};
13 ASSERT(gpu_addr);
14 14
15 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { 15 ASSERT_MSG(gpu_addr, "unable to find available GPU memory");
16 VAddr& slot = PageSlot(*gpu_addr + offset); 16
17 for (u64 offset{}; offset < size; offset += PAGE_SIZE) {
18 VAddr& slot{PageSlot(*gpu_addr + offset)};
17 19
18 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped)); 20 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
21
19 slot = static_cast<u64>(PageStatus::Allocated); 22 slot = static_cast<u64>(PageStatus::Allocated);
20 } 23 }
21 24
@@ -23,10 +26,11 @@ GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
23} 26}
24 27
25GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) { 28GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
26 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { 29 for (u64 offset{}; offset < size; offset += PAGE_SIZE) {
27 VAddr& slot = PageSlot(gpu_addr + offset); 30 VAddr& slot{PageSlot(gpu_addr + offset)};
28 31
29 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped)); 32 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
33
30 slot = static_cast<u64>(PageStatus::Allocated); 34 slot = static_cast<u64>(PageStatus::Allocated);
31 } 35 }
32 36
@@ -34,17 +38,19 @@ GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
34} 38}
35 39
36GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) { 40GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
37 std::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, PAGE_SIZE); 41 const std::optional<GPUVAddr> gpu_addr{FindFreeBlock(0, size, PAGE_SIZE, PageStatus::Unmapped)};
38 ASSERT(gpu_addr); 42
43 ASSERT_MSG(gpu_addr, "unable to find available GPU memory");
39 44
40 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { 45 for (u64 offset{}; offset < size; offset += PAGE_SIZE) {
41 VAddr& slot = PageSlot(*gpu_addr + offset); 46 VAddr& slot{PageSlot(*gpu_addr + offset)};
42 47
43 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped)); 48 ASSERT(slot == static_cast<u64>(PageStatus::Unmapped));
49
44 slot = cpu_addr + offset; 50 slot = cpu_addr + offset;
45 } 51 }
46 52
47 MappedRegion region{cpu_addr, *gpu_addr, size}; 53 const MappedRegion region{cpu_addr, *gpu_addr, size};
48 mapped_regions.push_back(region); 54 mapped_regions.push_back(region);
49 55
50 return *gpu_addr; 56 return *gpu_addr;
@@ -53,14 +59,31 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
53GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) { 59GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) {
54 ASSERT((gpu_addr & PAGE_MASK) == 0); 60 ASSERT((gpu_addr & PAGE_MASK) == 0);
55 61
56 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { 62 if (PageSlot(gpu_addr) != static_cast<u64>(PageStatus::Allocated)) {
57 VAddr& slot = PageSlot(gpu_addr + offset); 63 // Page has been already mapped. In this case, we must find a new area of memory to use that
64 // is different than the specified one. Super Mario Odyssey hits this scenario when changing
65 // areas, but we do not want to overwrite the old pages.
66 // TODO(bunnei): We need to write a hardware test to confirm this behavior.
67
68 LOG_ERROR(HW_GPU, "attempting to map addr 0x{:016X}, which is not available!", gpu_addr);
69
70 const std::optional<GPUVAddr> new_gpu_addr{
71 FindFreeBlock(gpu_addr, size, PAGE_SIZE, PageStatus::Allocated)};
72
73 ASSERT_MSG(new_gpu_addr, "unable to find available GPU memory");
74
75 gpu_addr = *new_gpu_addr;
76 }
77
78 for (u64 offset{}; offset < size; offset += PAGE_SIZE) {
79 VAddr& slot{PageSlot(gpu_addr + offset)};
58 80
59 ASSERT(slot == static_cast<u64>(PageStatus::Allocated)); 81 ASSERT(slot == static_cast<u64>(PageStatus::Allocated));
82
60 slot = cpu_addr + offset; 83 slot = cpu_addr + offset;
61 } 84 }
62 85
63 MappedRegion region{cpu_addr, gpu_addr, size}; 86 const MappedRegion region{cpu_addr, gpu_addr, size};
64 mapped_regions.push_back(region); 87 mapped_regions.push_back(region);
65 88
66 return gpu_addr; 89 return gpu_addr;
@@ -69,11 +92,12 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size)
69GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) { 92GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
70 ASSERT((gpu_addr & PAGE_MASK) == 0); 93 ASSERT((gpu_addr & PAGE_MASK) == 0);
71 94
72 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { 95 for (u64 offset{}; offset < size; offset += PAGE_SIZE) {
73 VAddr& slot = PageSlot(gpu_addr + offset); 96 VAddr& slot{PageSlot(gpu_addr + offset)};
74 97
75 ASSERT(slot != static_cast<u64>(PageStatus::Allocated) && 98 ASSERT(slot != static_cast<u64>(PageStatus::Allocated) &&
76 slot != static_cast<u64>(PageStatus::Unmapped)); 99 slot != static_cast<u64>(PageStatus::Unmapped));
100
77 slot = static_cast<u64>(PageStatus::Unmapped); 101 slot = static_cast<u64>(PageStatus::Unmapped);
78 } 102 }
79 103
@@ -97,13 +121,14 @@ GPUVAddr MemoryManager::GetRegionEnd(GPUVAddr region_start) const {
97 return {}; 121 return {};
98} 122}
99 123
100std::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) { 124std::optional<GPUVAddr> MemoryManager::FindFreeBlock(GPUVAddr region_start, u64 size, u64 align,
101 GPUVAddr gpu_addr = 0; 125 PageStatus status) {
102 u64 free_space = 0; 126 GPUVAddr gpu_addr{region_start};
127 u64 free_space{};
103 align = (align + PAGE_MASK) & ~PAGE_MASK; 128 align = (align + PAGE_MASK) & ~PAGE_MASK;
104 129
105 while (gpu_addr + free_space < MAX_ADDRESS) { 130 while (gpu_addr + free_space < MAX_ADDRESS) {
106 if (!IsPageMapped(gpu_addr + free_space)) { 131 if (PageSlot(gpu_addr + free_space) == static_cast<u64>(status)) {
107 free_space += PAGE_SIZE; 132 free_space += PAGE_SIZE;
108 if (free_space >= size) { 133 if (free_space >= size) {
109 return gpu_addr; 134 return gpu_addr;
@@ -119,7 +144,7 @@ std::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
119} 144}
120 145
121std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { 146std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) {
122 VAddr base_addr = PageSlot(gpu_addr); 147 const VAddr base_addr{PageSlot(gpu_addr)};
123 148
124 if (base_addr == static_cast<u64>(PageStatus::Allocated) || 149 if (base_addr == static_cast<u64>(PageStatus::Allocated) ||
125 base_addr == static_cast<u64>(PageStatus::Unmapped)) { 150 base_addr == static_cast<u64>(PageStatus::Unmapped)) {
@@ -133,19 +158,15 @@ std::vector<GPUVAddr> MemoryManager::CpuToGpuAddress(VAddr cpu_addr) const {
133 std::vector<GPUVAddr> results; 158 std::vector<GPUVAddr> results;
134 for (const auto& region : mapped_regions) { 159 for (const auto& region : mapped_regions) {
135 if (cpu_addr >= region.cpu_addr && cpu_addr < (region.cpu_addr + region.size)) { 160 if (cpu_addr >= region.cpu_addr && cpu_addr < (region.cpu_addr + region.size)) {
136 u64 offset = cpu_addr - region.cpu_addr; 161 const u64 offset{cpu_addr - region.cpu_addr};
137 results.push_back(region.gpu_addr + offset); 162 results.push_back(region.gpu_addr + offset);
138 } 163 }
139 } 164 }
140 return results; 165 return results;
141} 166}
142 167
143bool MemoryManager::IsPageMapped(GPUVAddr gpu_addr) {
144 return PageSlot(gpu_addr) != static_cast<u64>(PageStatus::Unmapped);
145}
146
147VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) { 168VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) {
148 auto& block = page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; 169 auto& block{page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]};
149 if (!block) { 170 if (!block) {
150 block = std::make_unique<PageBlock>(); 171 block = std::make_unique<PageBlock>();
151 block->fill(static_cast<VAddr>(PageStatus::Unmapped)); 172 block->fill(static_cast<VAddr>(PageStatus::Unmapped));
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index b1255fd56..4eb338aa2 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -34,15 +34,15 @@ public:
34 static constexpr u64 PAGE_MASK = PAGE_SIZE - 1; 34 static constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
35 35
36private: 36private:
37 std::optional<GPUVAddr> FindFreeBlock(u64 size, u64 align = 1);
38 bool IsPageMapped(GPUVAddr gpu_addr);
39 VAddr& PageSlot(GPUVAddr gpu_addr);
40
41 enum class PageStatus : u64 { 37 enum class PageStatus : u64 {
42 Unmapped = 0xFFFFFFFFFFFFFFFFULL, 38 Unmapped = 0xFFFFFFFFFFFFFFFFULL,
43 Allocated = 0xFFFFFFFFFFFFFFFEULL, 39 Allocated = 0xFFFFFFFFFFFFFFFEULL,
44 }; 40 };
45 41
42 std::optional<GPUVAddr> FindFreeBlock(GPUVAddr region_start, u64 size, u64 align,
43 PageStatus status);
44 VAddr& PageSlot(GPUVAddr gpu_addr);
45
46 static constexpr u64 MAX_ADDRESS{0x10000000000ULL}; 46 static constexpr u64 MAX_ADDRESS{0x10000000000ULL};
47 static constexpr u64 PAGE_TABLE_BITS{10}; 47 static constexpr u64 PAGE_TABLE_BITS{10};
48 static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS}; 48 static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a0527fe57..bb263b6aa 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -511,10 +511,10 @@ void RasterizerOpenGL::Clear() {
511 511
512 OpenGLState clear_state; 512 OpenGLState clear_state;
513 clear_state.draw.draw_framebuffer = framebuffer.handle; 513 clear_state.draw.draw_framebuffer = framebuffer.handle;
514 clear_state.color_mask.red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE; 514 clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
515 clear_state.color_mask.green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE; 515 clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
516 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE; 516 clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
517 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE; 517 clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
518 518
519 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 519 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
520 regs.clear_buffers.A) { 520 regs.clear_buffers.A) {
@@ -573,14 +573,13 @@ void RasterizerOpenGL::DrawArrays() {
573 ScopeAcquireGLContext acquire_context{emu_window}; 573 ScopeAcquireGLContext acquire_context{emu_window};
574 574
575 ConfigureFramebuffers(); 575 ConfigureFramebuffers();
576 576 SyncColorMask();
577 SyncDepthTestState(); 577 SyncDepthTestState();
578 SyncStencilTestState(); 578 SyncStencilTestState();
579 SyncBlendState(); 579 SyncBlendState();
580 SyncLogicOpState(); 580 SyncLogicOpState();
581 SyncCullMode(); 581 SyncCullMode();
582 SyncPrimitiveRestart(); 582 SyncPrimitiveRestart();
583 SyncDepthRange();
584 SyncScissorTest(); 583 SyncScissorTest();
585 // Alpha Testing is synced on shaders. 584 // Alpha Testing is synced on shaders.
586 SyncTransformFeedback(); 585 SyncTransformFeedback();
@@ -899,12 +898,16 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
899 898
900void RasterizerOpenGL::SyncViewport() { 899void RasterizerOpenGL::SyncViewport() {
901 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 900 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
902 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; 901 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
903 902 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
904 state.viewport.x = viewport_rect.left; 903 auto& viewport = state.viewports[i];
905 state.viewport.y = viewport_rect.bottom; 904 viewport.x = viewport_rect.left;
906 state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth()); 905 viewport.y = viewport_rect.bottom;
907 state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight()); 906 viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
907 viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
908 viewport.depth_range_far = regs.viewport[i].depth_range_far;
909 viewport.depth_range_near = regs.viewport[i].depth_range_near;
910 }
908} 911}
909 912
910void RasterizerOpenGL::SyncClipEnabled() { 913void RasterizerOpenGL::SyncClipEnabled() {
@@ -946,13 +949,6 @@ void RasterizerOpenGL::SyncPrimitiveRestart() {
946 state.primitive_restart.index = regs.primitive_restart.index; 949 state.primitive_restart.index = regs.primitive_restart.index;
947} 950}
948 951
949void RasterizerOpenGL::SyncDepthRange() {
950 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
951
952 state.depth.depth_range_near = regs.viewport->depth_range_near;
953 state.depth.depth_range_far = regs.viewport->depth_range_far;
954}
955
956void RasterizerOpenGL::SyncDepthTestState() { 952void RasterizerOpenGL::SyncDepthTestState() {
957 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 953 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
958 954
@@ -993,26 +989,60 @@ void RasterizerOpenGL::SyncStencilTestState() {
993 state.stencil.back.write_mask = regs.stencil_back_mask; 989 state.stencil.back.write_mask = regs.stencil_back_mask;
994} 990}
995 991
996void RasterizerOpenGL::SyncBlendState() { 992void RasterizerOpenGL::SyncColorMask() {
997 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 993 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
994 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
995 const auto& source = regs.color_mask[regs.color_mask_common ? 0 : i];
996 auto& dest = state.color_mask[i];
997 dest.red_enabled = (source.R == 0) ? GL_FALSE : GL_TRUE;
998 dest.green_enabled = (source.G == 0) ? GL_FALSE : GL_TRUE;
999 dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE;
1000 dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;
1001 }
1002}
998 1003
999 // TODO(Subv): Support more than just render target 0. 1004void RasterizerOpenGL::SyncBlendState() {
1000 state.blend.enabled = regs.blend.enable[0] != 0; 1005 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1001 1006
1002 if (!state.blend.enabled) 1007 state.blend_color.red = regs.blend_color.r;
1008 state.blend_color.green = regs.blend_color.g;
1009 state.blend_color.blue = regs.blend_color.b;
1010 state.blend_color.alpha = regs.blend_color.a;
1011
1012 state.independant_blend.enabled = regs.independent_blend_enable;
1013 if (!state.independant_blend.enabled) {
1014 auto& blend = state.blend[0];
1015 blend.enabled = regs.blend.enable[0] != 0;
1016 blend.separate_alpha = regs.blend.separate_alpha;
1017 blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
1018 blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
1019 blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
1020 if (blend.separate_alpha) {
1021 blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
1022 blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
1023 blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
1024 }
1025 for (size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
1026 state.blend[i].enabled = false;
1027 }
1003 return; 1028 return;
1029 }
1004 1030
1005 ASSERT_MSG(regs.logic_op.enable == 0, 1031 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
1006 "Blending and logic op can't be enabled at the same time."); 1032 auto& blend = state.blend[i];
1007 1033 blend.enabled = regs.blend.enable[i] != 0;
1008 ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); 1034 if (!blend.enabled)
1009 ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); 1035 continue;
1010 state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); 1036 blend.separate_alpha = regs.independent_blend[i].separate_alpha;
1011 state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_rgb); 1037 blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_rgb);
1012 state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_rgb); 1038 blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_rgb);
1013 state.blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_a); 1039 blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_rgb);
1014 state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); 1040 if (blend.separate_alpha) {
1015 state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); 1041 blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_a);
1042 blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_a);
1043 blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_a);
1044 }
1045 }
1016} 1046}
1017 1047
1018void RasterizerOpenGL::SyncLogicOpState() { 1048void RasterizerOpenGL::SyncLogicOpState() {
@@ -1031,19 +1061,19 @@ void RasterizerOpenGL::SyncLogicOpState() {
1031} 1061}
1032 1062
1033void RasterizerOpenGL::SyncScissorTest() { 1063void RasterizerOpenGL::SyncScissorTest() {
1064 // TODO: what is the correct behavior here, a single scissor for all targets
1065 // or scissor disabled for the rest of the targets?
1034 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 1066 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1035
1036 state.scissor.enabled = (regs.scissor_test.enable != 0); 1067 state.scissor.enabled = (regs.scissor_test.enable != 0);
1037 // TODO(Blinkhawk): Figure if the hardware supports scissor testing per viewport and how it's 1068 if (regs.scissor_test.enable == 0) {
1038 // implemented. 1069 return;
1039 if (regs.scissor_test.enable != 0) {
1040 const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
1041 const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
1042 state.scissor.x = regs.scissor_test.min_x;
1043 state.scissor.y = regs.scissor_test.min_y;
1044 state.scissor.width = width;
1045 state.scissor.height = height;
1046 } 1070 }
1071 const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
1072 const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
1073 state.scissor.x = regs.scissor_test.min_x;
1074 state.scissor.y = regs.scissor_test.min_y;
1075 state.scissor.width = width;
1076 state.scissor.height = height;
1047} 1077}
1048 1078
1049void RasterizerOpenGL::SyncTransformFeedback() { 1079void RasterizerOpenGL::SyncTransformFeedback() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 47097c569..60e783803 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -133,7 +133,7 @@ private:
133 u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, 133 u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
134 GLenum primitive_mode, u32 current_unit); 134 GLenum primitive_mode, u32 current_unit);
135 135
136 /// Syncs the viewport to match the guest state 136 /// Syncs the viewport and depth range to match the guest state
137 void SyncViewport(); 137 void SyncViewport();
138 138
139 /// Syncs the clip enabled status to match the guest state 139 /// Syncs the clip enabled status to match the guest state
@@ -148,9 +148,6 @@ private:
148 /// Syncs the primitve restart to match the guest state 148 /// Syncs the primitve restart to match the guest state
149 void SyncPrimitiveRestart(); 149 void SyncPrimitiveRestart();
150 150
151 /// Syncs the depth range to match the guest state
152 void SyncDepthRange();
153
154 /// Syncs the depth test state to match the guest state 151 /// Syncs the depth test state to match the guest state
155 void SyncDepthTestState(); 152 void SyncDepthTestState();
156 153
@@ -172,6 +169,9 @@ private:
172 /// Syncs the point state to match the guest state 169 /// Syncs the point state to match the guest state
173 void SyncPointState(); 170 void SyncPointState();
174 171
172 /// Syncs Color Mask
173 void SyncColorMask();
174
175 /// Check asserts for alpha testing. 175 /// Check asserts for alpha testing.
176 void CheckAlphaTests(); 176 void CheckAlphaTests();
177 177
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 7d970efa0..49d63e6f3 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -562,9 +562,11 @@ void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params
562 } 562 }
563} 563}
564 564
565MICROPROFILE_DEFINE(OpenGL_BlitSurface, "OpenGL", "BlitSurface", MP_RGB(128, 192, 64));
565static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface, 566static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
566 GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0, 567 GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0,
567 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) { 568 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
569 MICROPROFILE_SCOPE(OpenGL_BlitSurface);
568 570
569 const auto& src_params{src_surface->GetSurfaceParams()}; 571 const auto& src_params{src_surface->GetSurfaceParams()};
570 const auto& dst_params{dst_surface->GetSurfaceParams()}; 572 const auto& dst_params{dst_surface->GetSurfaceParams()};
@@ -704,9 +706,11 @@ static void FastCopySurface(const Surface& src_surface, const Surface& dst_surfa
704 0, 0, width, height, 1); 706 0, 0, width, height, 1);
705} 707}
706 708
709MICROPROFILE_DEFINE(OpenGL_CopySurface, "OpenGL", "CopySurface", MP_RGB(128, 192, 64));
707static void CopySurface(const Surface& src_surface, const Surface& dst_surface, 710static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
708 GLuint copy_pbo_handle, GLenum src_attachment = 0, 711 GLuint copy_pbo_handle, GLenum src_attachment = 0,
709 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) { 712 GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
713 MICROPROFILE_SCOPE(OpenGL_CopySurface);
710 ASSERT_MSG(dst_attachment == 0, "Unimplemented"); 714 ASSERT_MSG(dst_attachment == 0, "Unimplemented");
711 715
712 const auto& src_params{src_surface->GetSurfaceParams()}; 716 const auto& src_params{src_surface->GetSurfaceParams()};
@@ -975,7 +979,7 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm
975 } 979 }
976} 980}
977 981
978MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); 982MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64));
979void CachedSurface::LoadGLBuffer() { 983void CachedSurface::LoadGLBuffer() {
980 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); 984 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
981 gl_buffer.resize(params.max_mip_level); 985 gl_buffer.resize(params.max_mip_level);
@@ -1157,7 +1161,7 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
1157 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 1161 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1158} 1162}
1159 1163
1160MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192)); 1164MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
1161void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { 1165void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
1162 if (params.type == SurfaceType::Fill) 1166 if (params.type == SurfaceType::Fill)
1163 return; 1167 return;
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
index c10863337..161318c5f 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp
@@ -5,21 +5,31 @@
5#include <utility> 5#include <utility>
6#include <glad/glad.h> 6#include <glad/glad.h>
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/microprofile.h"
8#include "video_core/renderer_opengl/gl_resource_manager.h" 9#include "video_core/renderer_opengl/gl_resource_manager.h"
9#include "video_core/renderer_opengl/gl_shader_util.h" 10#include "video_core/renderer_opengl/gl_shader_util.h"
10#include "video_core/renderer_opengl/gl_state.h" 11#include "video_core/renderer_opengl/gl_state.h"
11 12
13MICROPROFILE_DEFINE(OpenGL_ResourceCreation, "OpenGL", "Resource Creation",
14 MP_RGB(128, 128, 192));
15MICROPROFILE_DEFINE(OpenGL_ResourceDeletion, "OpenGL", "Resource Deletion",
16 MP_RGB(128, 128, 192));
17
12namespace OpenGL { 18namespace OpenGL {
13 19
14void OGLTexture::Create() { 20void OGLTexture::Create() {
15 if (handle != 0) 21 if (handle != 0)
16 return; 22 return;
23
24 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
17 glGenTextures(1, &handle); 25 glGenTextures(1, &handle);
18} 26}
19 27
20void OGLTexture::Release() { 28void OGLTexture::Release() {
21 if (handle == 0) 29 if (handle == 0)
22 return; 30 return;
31
32 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
23 glDeleteTextures(1, &handle); 33 glDeleteTextures(1, &handle);
24 OpenGLState::GetCurState().UnbindTexture(handle).Apply(); 34 OpenGLState::GetCurState().UnbindTexture(handle).Apply();
25 handle = 0; 35 handle = 0;
@@ -28,12 +38,16 @@ void OGLTexture::Release() {
28void OGLSampler::Create() { 38void OGLSampler::Create() {
29 if (handle != 0) 39 if (handle != 0)
30 return; 40 return;
41
42 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
31 glGenSamplers(1, &handle); 43 glGenSamplers(1, &handle);
32} 44}
33 45
34void OGLSampler::Release() { 46void OGLSampler::Release() {
35 if (handle == 0) 47 if (handle == 0)
36 return; 48 return;
49
50 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
37 glDeleteSamplers(1, &handle); 51 glDeleteSamplers(1, &handle);
38 OpenGLState::GetCurState().ResetSampler(handle).Apply(); 52 OpenGLState::GetCurState().ResetSampler(handle).Apply();
39 handle = 0; 53 handle = 0;
@@ -44,12 +58,16 @@ void OGLShader::Create(const char* source, GLenum type) {
44 return; 58 return;
45 if (source == nullptr) 59 if (source == nullptr)
46 return; 60 return;
61
62 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
47 handle = GLShader::LoadShader(source, type); 63 handle = GLShader::LoadShader(source, type);
48} 64}
49 65
50void OGLShader::Release() { 66void OGLShader::Release() {
51 if (handle == 0) 67 if (handle == 0)
52 return; 68 return;
69
70 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
53 glDeleteShader(handle); 71 glDeleteShader(handle);
54 handle = 0; 72 handle = 0;
55} 73}
@@ -63,12 +81,16 @@ void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shade
63 geo.Create(geo_shader, GL_GEOMETRY_SHADER); 81 geo.Create(geo_shader, GL_GEOMETRY_SHADER);
64 if (frag_shader) 82 if (frag_shader)
65 frag.Create(frag_shader, GL_FRAGMENT_SHADER); 83 frag.Create(frag_shader, GL_FRAGMENT_SHADER);
84
85 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
66 Create(separable_program, vert.handle, geo.handle, frag.handle); 86 Create(separable_program, vert.handle, geo.handle, frag.handle);
67} 87}
68 88
69void OGLProgram::Release() { 89void OGLProgram::Release() {
70 if (handle == 0) 90 if (handle == 0)
71 return; 91 return;
92
93 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
72 glDeleteProgram(handle); 94 glDeleteProgram(handle);
73 OpenGLState::GetCurState().ResetProgram(handle).Apply(); 95 OpenGLState::GetCurState().ResetProgram(handle).Apply();
74 handle = 0; 96 handle = 0;
@@ -77,12 +99,16 @@ void OGLProgram::Release() {
77void OGLPipeline::Create() { 99void OGLPipeline::Create() {
78 if (handle != 0) 100 if (handle != 0)
79 return; 101 return;
102
103 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
80 glGenProgramPipelines(1, &handle); 104 glGenProgramPipelines(1, &handle);
81} 105}
82 106
83void OGLPipeline::Release() { 107void OGLPipeline::Release() {
84 if (handle == 0) 108 if (handle == 0)
85 return; 109 return;
110
111 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
86 glDeleteProgramPipelines(1, &handle); 112 glDeleteProgramPipelines(1, &handle);
87 OpenGLState::GetCurState().ResetPipeline(handle).Apply(); 113 OpenGLState::GetCurState().ResetPipeline(handle).Apply();
88 handle = 0; 114 handle = 0;
@@ -91,12 +117,16 @@ void OGLPipeline::Release() {
91void OGLBuffer::Create() { 117void OGLBuffer::Create() {
92 if (handle != 0) 118 if (handle != 0)
93 return; 119 return;
120
121 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
94 glGenBuffers(1, &handle); 122 glGenBuffers(1, &handle);
95} 123}
96 124
97void OGLBuffer::Release() { 125void OGLBuffer::Release() {
98 if (handle == 0) 126 if (handle == 0)
99 return; 127 return;
128
129 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
100 glDeleteBuffers(1, &handle); 130 glDeleteBuffers(1, &handle);
101 OpenGLState::GetCurState().ResetBuffer(handle).Apply(); 131 OpenGLState::GetCurState().ResetBuffer(handle).Apply();
102 handle = 0; 132 handle = 0;
@@ -105,12 +135,16 @@ void OGLBuffer::Release() {
105void OGLSync::Create() { 135void OGLSync::Create() {
106 if (handle != 0) 136 if (handle != 0)
107 return; 137 return;
138
139 // Don't profile here, this one is expected to happen ingame.
108 handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 140 handle = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
109} 141}
110 142
111void OGLSync::Release() { 143void OGLSync::Release() {
112 if (handle == 0) 144 if (handle == 0)
113 return; 145 return;
146
147 // Don't profile here, this one is expected to happen ingame.
114 glDeleteSync(handle); 148 glDeleteSync(handle);
115 handle = 0; 149 handle = 0;
116} 150}
@@ -118,12 +152,16 @@ void OGLSync::Release() {
118void OGLVertexArray::Create() { 152void OGLVertexArray::Create() {
119 if (handle != 0) 153 if (handle != 0)
120 return; 154 return;
155
156 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
121 glGenVertexArrays(1, &handle); 157 glGenVertexArrays(1, &handle);
122} 158}
123 159
124void OGLVertexArray::Release() { 160void OGLVertexArray::Release() {
125 if (handle == 0) 161 if (handle == 0)
126 return; 162 return;
163
164 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
127 glDeleteVertexArrays(1, &handle); 165 glDeleteVertexArrays(1, &handle);
128 OpenGLState::GetCurState().ResetVertexArray(handle).Apply(); 166 OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
129 handle = 0; 167 handle = 0;
@@ -132,12 +170,16 @@ void OGLVertexArray::Release() {
132void OGLFramebuffer::Create() { 170void OGLFramebuffer::Create() {
133 if (handle != 0) 171 if (handle != 0)
134 return; 172 return;
173
174 MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
135 glGenFramebuffers(1, &handle); 175 glGenFramebuffers(1, &handle);
136} 176}
137 177
138void OGLFramebuffer::Release() { 178void OGLFramebuffer::Release() {
139 if (handle == 0) 179 if (handle == 0)
140 return; 180 return;
181
182 MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
141 glDeleteFramebuffers(1, &handle); 183 glDeleteFramebuffers(1, &handle);
142 OpenGLState::GetCurState().ResetFramebuffer(handle).Apply(); 184 OpenGLState::GetCurState().ResetFramebuffer(handle).Apply();
143 handle = 0; 185 handle = 0;
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index b6b426f34..9517285e5 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -22,17 +22,15 @@ OpenGLState::OpenGLState() {
22 depth.test_enabled = false; 22 depth.test_enabled = false;
23 depth.test_func = GL_LESS; 23 depth.test_func = GL_LESS;
24 depth.write_mask = GL_TRUE; 24 depth.write_mask = GL_TRUE;
25 depth.depth_range_near = 0.0f;
26 depth.depth_range_far = 1.0f;
27 25
28 primitive_restart.enabled = false; 26 primitive_restart.enabled = false;
29 primitive_restart.index = 0; 27 primitive_restart.index = 0;
30 28 for (auto& item : color_mask) {
31 color_mask.red_enabled = GL_TRUE; 29 item.red_enabled = GL_TRUE;
32 color_mask.green_enabled = GL_TRUE; 30 item.green_enabled = GL_TRUE;
33 color_mask.blue_enabled = GL_TRUE; 31 item.blue_enabled = GL_TRUE;
34 color_mask.alpha_enabled = GL_TRUE; 32 item.alpha_enabled = GL_TRUE;
35 33 }
36 stencil.test_enabled = false; 34 stencil.test_enabled = false;
37 auto reset_stencil = [](auto& config) { 35 auto reset_stencil = [](auto& config) {
38 config.test_func = GL_ALWAYS; 36 config.test_func = GL_ALWAYS;
@@ -45,19 +43,33 @@ OpenGLState::OpenGLState() {
45 }; 43 };
46 reset_stencil(stencil.front); 44 reset_stencil(stencil.front);
47 reset_stencil(stencil.back); 45 reset_stencil(stencil.back);
48 46 for (auto& item : viewports) {
49 blend.enabled = true; 47 item.x = 0;
50 blend.rgb_equation = GL_FUNC_ADD; 48 item.y = 0;
51 blend.a_equation = GL_FUNC_ADD; 49 item.width = 0;
52 blend.src_rgb_func = GL_ONE; 50 item.height = 0;
53 blend.dst_rgb_func = GL_ZERO; 51 item.depth_range_near = 0.0f;
54 blend.src_a_func = GL_ONE; 52 item.depth_range_far = 1.0f;
55 blend.dst_a_func = GL_ZERO; 53 }
56 blend.color.red = 0.0f; 54 scissor.enabled = false;
57 blend.color.green = 0.0f; 55 scissor.x = 0;
58 blend.color.blue = 0.0f; 56 scissor.y = 0;
59 blend.color.alpha = 0.0f; 57 scissor.width = 0;
60 58 scissor.height = 0;
59 for (auto& item : blend) {
60 item.enabled = true;
61 item.rgb_equation = GL_FUNC_ADD;
62 item.a_equation = GL_FUNC_ADD;
63 item.src_rgb_func = GL_ONE;
64 item.dst_rgb_func = GL_ZERO;
65 item.src_a_func = GL_ONE;
66 item.dst_a_func = GL_ZERO;
67 }
68 independant_blend.enabled = false;
69 blend_color.red = 0.0f;
70 blend_color.green = 0.0f;
71 blend_color.blue = 0.0f;
72 blend_color.alpha = 0.0f;
61 logic_op.enabled = false; 73 logic_op.enabled = false;
62 logic_op.operation = GL_COPY; 74 logic_op.operation = GL_COPY;
63 75
@@ -73,17 +85,6 @@ OpenGLState::OpenGLState() {
73 draw.shader_program = 0; 85 draw.shader_program = 0;
74 draw.program_pipeline = 0; 86 draw.program_pipeline = 0;
75 87
76 scissor.enabled = false;
77 scissor.x = 0;
78 scissor.y = 0;
79 scissor.width = 0;
80 scissor.height = 0;
81
82 viewport.x = 0;
83 viewport.y = 0;
84 viewport.width = 0;
85 viewport.height = 0;
86
87 clip_distance = {}; 88 clip_distance = {};
88 89
89 point.size = 1; 90 point.size = 1;
@@ -134,6 +135,32 @@ void OpenGLState::ApplyCulling() const {
134 } 135 }
135} 136}
136 137
138void OpenGLState::ApplyColorMask() const {
139 if (GLAD_GL_ARB_viewport_array) {
140 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
141 const auto& updated = color_mask[i];
142 const auto& current = cur_state.color_mask[i];
143 if (updated.red_enabled != current.red_enabled ||
144 updated.green_enabled != current.green_enabled ||
145 updated.blue_enabled != current.blue_enabled ||
146 updated.alpha_enabled != current.alpha_enabled) {
147 glColorMaski(static_cast<GLuint>(i), updated.red_enabled, updated.green_enabled,
148 updated.blue_enabled, updated.alpha_enabled);
149 }
150 }
151 } else {
152 const auto& updated = color_mask[0];
153 const auto& current = cur_state.color_mask[0];
154 if (updated.red_enabled != current.red_enabled ||
155 updated.green_enabled != current.green_enabled ||
156 updated.blue_enabled != current.blue_enabled ||
157 updated.alpha_enabled != current.alpha_enabled) {
158 glColorMask(updated.red_enabled, updated.green_enabled, updated.blue_enabled,
159 updated.alpha_enabled);
160 }
161 }
162}
163
137void OpenGLState::ApplyDepth() const { 164void OpenGLState::ApplyDepth() const {
138 // Depth test 165 // Depth test
139 const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled; 166 const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled;
@@ -152,11 +179,6 @@ void OpenGLState::ApplyDepth() const {
152 if (depth.write_mask != cur_state.depth.write_mask) { 179 if (depth.write_mask != cur_state.depth.write_mask) {
153 glDepthMask(depth.write_mask); 180 glDepthMask(depth.write_mask);
154 } 181 }
155 // Depth range
156 if (depth.depth_range_near != cur_state.depth.depth_range_near ||
157 depth.depth_range_far != cur_state.depth.depth_range_far) {
158 glDepthRange(depth.depth_range_near, depth.depth_range_far);
159 }
160} 182}
161 183
162void OpenGLState::ApplyPrimitiveRestart() const { 184void OpenGLState::ApplyPrimitiveRestart() const {
@@ -208,7 +230,7 @@ void OpenGLState::ApplyStencilTest() const {
208 } 230 }
209} 231}
210 232
211void OpenGLState::ApplyScissorTest() const { 233void OpenGLState::ApplyScissor() const {
212 const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled; 234 const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
213 if (scissor_changed) { 235 if (scissor_changed) {
214 if (scissor.enabled) { 236 if (scissor.enabled) {
@@ -217,51 +239,141 @@ void OpenGLState::ApplyScissorTest() const {
217 glDisable(GL_SCISSOR_TEST); 239 glDisable(GL_SCISSOR_TEST);
218 } 240 }
219 } 241 }
220 if (scissor_changed || scissor_changed || scissor.x != cur_state.scissor.x || 242 if (scissor.enabled &&
221 scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width || 243 (scissor_changed || scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
222 scissor.height != cur_state.scissor.height) { 244 scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height)) {
223 glScissor(scissor.x, scissor.y, scissor.width, scissor.height); 245 glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
224 } 246 }
225} 247}
226 248
227void OpenGLState::ApplyBlending() const { 249void OpenGLState::ApplyViewport() const {
228 const bool blend_changed = blend.enabled != cur_state.blend.enabled; 250 if (GLAD_GL_ARB_viewport_array) {
251 for (GLuint i = 0;
252 i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); i++) {
253 const auto& current = cur_state.viewports[i];
254 const auto& updated = viewports[i];
255 if (updated.x != current.x || updated.y != current.y ||
256 updated.width != current.width || updated.height != current.height) {
257 glViewportIndexedf(i, updated.x, updated.y, updated.width, updated.height);
258 }
259 if (updated.depth_range_near != current.depth_range_near ||
260 updated.depth_range_far != current.depth_range_far) {
261 glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far);
262 }
263 }
264 } else {
265 const auto& current = cur_state.viewports[0];
266 const auto& updated = viewports[0];
267 if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
268 updated.height != current.height) {
269 glViewport(updated.x, updated.y, updated.width, updated.height);
270 }
271 if (updated.depth_range_near != current.depth_range_near ||
272 updated.depth_range_far != current.depth_range_far) {
273 glDepthRange(updated.depth_range_near, updated.depth_range_far);
274 }
275 }
276}
277
278void OpenGLState::ApplyGlobalBlending() const {
279 const Blend& current = cur_state.blend[0];
280 const Blend& updated = blend[0];
281 const bool blend_changed = updated.enabled != current.enabled;
229 if (blend_changed) { 282 if (blend_changed) {
230 if (blend.enabled) { 283 if (updated.enabled) {
231 ASSERT(!logic_op.enabled);
232 glEnable(GL_BLEND); 284 glEnable(GL_BLEND);
233 } else { 285 } else {
234 glDisable(GL_BLEND); 286 glDisable(GL_BLEND);
235 } 287 }
236 } 288 }
237 if (blend.enabled) { 289 if (!updated.enabled) {
238 if (blend_changed || blend.color.red != cur_state.blend.color.red || 290 return;
239 blend.color.green != cur_state.blend.color.green || 291 }
240 blend.color.blue != cur_state.blend.color.blue || 292 if (updated.separate_alpha) {
241 blend.color.alpha != cur_state.blend.color.alpha) { 293 if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
242 glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha); 294 updated.dst_rgb_func != current.dst_rgb_func ||
295 updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
296 glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func,
297 updated.dst_a_func);
243 } 298 }
244 299
245 if (blend_changed || blend.src_rgb_func != cur_state.blend.src_rgb_func || 300 if (blend_changed || updated.rgb_equation != current.rgb_equation ||
246 blend.dst_rgb_func != cur_state.blend.dst_rgb_func || 301 updated.a_equation != current.a_equation) {
247 blend.src_a_func != cur_state.blend.src_a_func || 302 glBlendEquationSeparate(updated.rgb_equation, updated.a_equation);
248 blend.dst_a_func != cur_state.blend.dst_a_func) { 303 }
249 glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, 304 } else {
250 blend.dst_a_func); 305 if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
306 updated.dst_rgb_func != current.dst_rgb_func) {
307 glBlendFunc(updated.src_rgb_func, updated.dst_rgb_func);
251 } 308 }
252 309
253 if (blend_changed || blend.rgb_equation != cur_state.blend.rgb_equation || 310 if (blend_changed || updated.rgb_equation != current.rgb_equation) {
254 blend.a_equation != cur_state.blend.a_equation) { 311 glBlendEquation(updated.rgb_equation);
255 glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
256 } 312 }
257 } 313 }
258} 314}
259 315
316void OpenGLState::ApplyTargetBlending(int target, bool force) const {
317 const Blend& updated = blend[target];
318 const Blend& current = cur_state.blend[target];
319 const bool blend_changed = updated.enabled != current.enabled || force;
320 if (blend_changed) {
321 if (updated.enabled) {
322 glEnablei(GL_BLEND, static_cast<GLuint>(target));
323 } else {
324 glDisablei(GL_BLEND, static_cast<GLuint>(target));
325 }
326 }
327 if (!updated.enabled) {
328 return;
329 }
330 if (updated.separate_alpha) {
331 if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
332 updated.dst_rgb_func != current.dst_rgb_func ||
333 updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
334 glBlendFuncSeparateiARB(static_cast<GLuint>(target), updated.src_rgb_func,
335 updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func);
336 }
337
338 if (blend_changed || updated.rgb_equation != current.rgb_equation ||
339 updated.a_equation != current.a_equation) {
340 glBlendEquationSeparateiARB(static_cast<GLuint>(target), updated.rgb_equation,
341 updated.a_equation);
342 }
343 } else {
344 if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
345 updated.dst_rgb_func != current.dst_rgb_func) {
346 glBlendFunciARB(static_cast<GLuint>(target), updated.src_rgb_func,
347 updated.dst_rgb_func);
348 }
349
350 if (blend_changed || updated.rgb_equation != current.rgb_equation) {
351 glBlendEquationiARB(static_cast<GLuint>(target), updated.rgb_equation);
352 }
353 }
354}
355
356void OpenGLState::ApplyBlending() const {
357 if (independant_blend.enabled) {
358 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
359 ApplyTargetBlending(i,
360 independant_blend.enabled != cur_state.independant_blend.enabled);
361 }
362 } else {
363 ApplyGlobalBlending();
364 }
365 if (blend_color.red != cur_state.blend_color.red ||
366 blend_color.green != cur_state.blend_color.green ||
367 blend_color.blue != cur_state.blend_color.blue ||
368 blend_color.alpha != cur_state.blend_color.alpha) {
369 glBlendColor(blend_color.red, blend_color.green, blend_color.blue, blend_color.alpha);
370 }
371}
372
260void OpenGLState::ApplyLogicOp() const { 373void OpenGLState::ApplyLogicOp() const {
261 const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled; 374 const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
262 if (logic_op_changed) { 375 if (logic_op_changed) {
263 if (logic_op.enabled) { 376 if (logic_op.enabled) {
264 ASSERT(!blend.enabled);
265 glEnable(GL_COLOR_LOGIC_OP); 377 glEnable(GL_COLOR_LOGIC_OP);
266 } else { 378 } else {
267 glDisable(GL_COLOR_LOGIC_OP); 379 glDisable(GL_COLOR_LOGIC_OP);
@@ -348,12 +460,6 @@ void OpenGLState::Apply() const {
348 if (draw.program_pipeline != cur_state.draw.program_pipeline) { 460 if (draw.program_pipeline != cur_state.draw.program_pipeline) {
349 glBindProgramPipeline(draw.program_pipeline); 461 glBindProgramPipeline(draw.program_pipeline);
350 } 462 }
351 // Viewport
352 if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y ||
353 viewport.width != cur_state.viewport.width ||
354 viewport.height != cur_state.viewport.height) {
355 glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
356 }
357 // Clip distance 463 // Clip distance
358 for (std::size_t i = 0; i < clip_distance.size(); ++i) { 464 for (std::size_t i = 0; i < clip_distance.size(); ++i) {
359 if (clip_distance[i] != cur_state.clip_distance[i]) { 465 if (clip_distance[i] != cur_state.clip_distance[i]) {
@@ -364,19 +470,13 @@ void OpenGLState::Apply() const {
364 } 470 }
365 } 471 }
366 } 472 }
367 // Color mask
368 if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
369 color_mask.green_enabled != cur_state.color_mask.green_enabled ||
370 color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
371 color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
372 glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
373 color_mask.alpha_enabled);
374 }
375 // Point 473 // Point
376 if (point.size != cur_state.point.size) { 474 if (point.size != cur_state.point.size) {
377 glPointSize(point.size); 475 glPointSize(point.size);
378 } 476 }
379 ApplyScissorTest(); 477 ApplyColorMask();
478 ApplyViewport();
479 ApplyScissor();
380 ApplyStencilTest(); 480 ApplyStencilTest();
381 ApplySRgb(); 481 ApplySRgb();
382 ApplyCulling(); 482 ApplyCulling();
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index fe648aff6..b8cf1f637 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -46,11 +46,9 @@ public:
46 } cull; 46 } cull;
47 47
48 struct { 48 struct {
49 bool test_enabled; // GL_DEPTH_TEST 49 bool test_enabled; // GL_DEPTH_TEST
50 GLenum test_func; // GL_DEPTH_FUNC 50 GLenum test_func; // GL_DEPTH_FUNC
51 GLboolean write_mask; // GL_DEPTH_WRITEMASK 51 GLboolean write_mask; // GL_DEPTH_WRITEMASK
52 GLfloat depth_range_near; // GL_DEPTH_RANGE
53 GLfloat depth_range_far; // GL_DEPTH_RANGE
54 } depth; 52 } depth;
55 53
56 struct { 54 struct {
@@ -58,13 +56,14 @@ public:
58 GLuint index; 56 GLuint index;
59 } primitive_restart; // GL_PRIMITIVE_RESTART 57 } primitive_restart; // GL_PRIMITIVE_RESTART
60 58
61 struct { 59 struct ColorMask {
62 GLboolean red_enabled; 60 GLboolean red_enabled;
63 GLboolean green_enabled; 61 GLboolean green_enabled;
64 GLboolean blue_enabled; 62 GLboolean blue_enabled;
65 GLboolean alpha_enabled; 63 GLboolean alpha_enabled;
66 } color_mask; // GL_COLOR_WRITEMASK 64 };
67 65 std::array<ColorMask, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets>
66 color_mask; // GL_COLOR_WRITEMASK
68 struct { 67 struct {
69 bool test_enabled; // GL_STENCIL_TEST 68 bool test_enabled; // GL_STENCIL_TEST
70 struct { 69 struct {
@@ -78,22 +77,28 @@ public:
78 } front, back; 77 } front, back;
79 } stencil; 78 } stencil;
80 79
81 struct { 80 struct Blend {
82 bool enabled; // GL_BLEND 81 bool enabled; // GL_BLEND
82 bool separate_alpha; // Independent blend enabled
83 GLenum rgb_equation; // GL_BLEND_EQUATION_RGB 83 GLenum rgb_equation; // GL_BLEND_EQUATION_RGB
84 GLenum a_equation; // GL_BLEND_EQUATION_ALPHA 84 GLenum a_equation; // GL_BLEND_EQUATION_ALPHA
85 GLenum src_rgb_func; // GL_BLEND_SRC_RGB 85 GLenum src_rgb_func; // GL_BLEND_SRC_RGB
86 GLenum dst_rgb_func; // GL_BLEND_DST_RGB 86 GLenum dst_rgb_func; // GL_BLEND_DST_RGB
87 GLenum src_a_func; // GL_BLEND_SRC_ALPHA 87 GLenum src_a_func; // GL_BLEND_SRC_ALPHA
88 GLenum dst_a_func; // GL_BLEND_DST_ALPHA 88 GLenum dst_a_func; // GL_BLEND_DST_ALPHA
89 };
90 std::array<Blend, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> blend;
89 91
90 struct { 92 struct {
91 GLclampf red; 93 bool enabled;
92 GLclampf green; 94 } independant_blend;
93 GLclampf blue; 95
94 GLclampf alpha; 96 struct {
95 } color; // GL_BLEND_COLOR 97 GLclampf red;
96 } blend; 98 GLclampf green;
99 GLclampf blue;
100 GLclampf alpha;
101 } blend_color; // GL_BLEND_COLOR
97 102
98 struct { 103 struct {
99 bool enabled; // GL_LOGIC_OP_MODE 104 bool enabled; // GL_LOGIC_OP_MODE
@@ -138,6 +143,16 @@ public:
138 GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING 143 GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
139 } draw; 144 } draw;
140 145
146 struct viewport {
147 GLfloat x;
148 GLfloat y;
149 GLfloat width;
150 GLfloat height;
151 GLfloat depth_range_near; // GL_DEPTH_RANGE
152 GLfloat depth_range_far; // GL_DEPTH_RANGE
153 };
154 std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> viewports;
155
141 struct { 156 struct {
142 bool enabled; // GL_SCISSOR_TEST 157 bool enabled; // GL_SCISSOR_TEST
143 GLint x; 158 GLint x;
@@ -147,13 +162,6 @@ public:
147 } scissor; 162 } scissor;
148 163
149 struct { 164 struct {
150 GLint x;
151 GLint y;
152 GLsizei width;
153 GLsizei height;
154 } viewport;
155
156 struct {
157 float size; // GL_POINT_SIZE 165 float size; // GL_POINT_SIZE
158 } point; 166 } point;
159 167
@@ -191,14 +199,18 @@ private:
191 static bool s_rgb_used; 199 static bool s_rgb_used;
192 void ApplySRgb() const; 200 void ApplySRgb() const;
193 void ApplyCulling() const; 201 void ApplyCulling() const;
202 void ApplyColorMask() const;
194 void ApplyDepth() const; 203 void ApplyDepth() const;
195 void ApplyPrimitiveRestart() const; 204 void ApplyPrimitiveRestart() const;
196 void ApplyStencilTest() const; 205 void ApplyStencilTest() const;
197 void ApplyScissorTest() const; 206 void ApplyViewport() const;
207 void ApplyTargetBlending(int target, bool force) const;
208 void ApplyGlobalBlending() const;
198 void ApplyBlending() const; 209 void ApplyBlending() const;
199 void ApplyLogicOp() const; 210 void ApplyLogicOp() const;
200 void ApplyTextures() const; 211 void ApplyTextures() const;
201 void ApplySamplers() const; 212 void ApplySamplers() const;
213 void ApplyScissor() const;
202}; 214};
203 215
204} // namespace OpenGL 216} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index e409228cc..b97b895a4 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -6,9 +6,13 @@
6#include <vector> 6#include <vector>
7#include "common/alignment.h" 7#include "common/alignment.h"
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/microprofile.h"
9#include "video_core/renderer_opengl/gl_state.h" 10#include "video_core/renderer_opengl/gl_state.h"
10#include "video_core/renderer_opengl/gl_stream_buffer.h" 11#include "video_core/renderer_opengl/gl_stream_buffer.h"
11 12
13MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning",
14 MP_RGB(128, 128, 192));
15
12namespace OpenGL { 16namespace OpenGL {
13 17
14OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent) 18OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent)
@@ -75,6 +79,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a
75 } 79 }
76 80
77 if (invalidate || !persistent) { 81 if (invalidate || !persistent) {
82 MICROPROFILE_SCOPE(OpenGL_StreamBuffer);
78 GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) | 83 GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) |
79 (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | 84 (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) |
80 (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); 85 (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT);