summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp41
-rw-r--r--src/core/hle/kernel/shared_memory.cpp2
-rw-r--r--src/core/hle/service/apt/apt.cpp2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp11
-rw-r--r--src/core/hle/service/y2r_u.cpp4
-rw-r--r--src/core/memory.cpp128
-rw-r--r--src/core/memory.h34
-rw-r--r--src/network/room.cpp5
-rw-r--r--src/network/room.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp65
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp50
-rw-r--r--src/video_core/renderer_opengl/gl_state.h10
15 files changed, 220 insertions, 168 deletions
diff --git a/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp
index e3f3194db..7f4ec0c52 100644
--- a/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp
+++ b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp
@@ -183,23 +183,13 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
183 print_input(output, src1, swizzle.negate_src1, 183 print_input(output, src1, swizzle.negate_src1,
184 SelectorToString(swizzle.src1_selector)); 184 SelectorToString(swizzle.src1_selector));
185 AlignToColumn(kInputOperandColumnWidth); 185 AlignToColumn(kInputOperandColumnWidth);
186 if (src_is_inverted) { 186 print_input(output, src2, swizzle.negate_src2,
187 print_input(output, src2, swizzle.negate_src2, 187 SelectorToString(swizzle.src2_selector), true,
188 SelectorToString(swizzle.src2_selector)); 188 src_is_inverted ? "" : instr.mad.AddressRegisterName());
189 } else {
190 print_input(output, src2, swizzle.negate_src2,
191 SelectorToString(swizzle.src2_selector), true,
192 instr.mad.AddressRegisterName());
193 }
194 AlignToColumn(kInputOperandColumnWidth); 189 AlignToColumn(kInputOperandColumnWidth);
195 if (src_is_inverted) { 190 print_input(output, src3, swizzle.negate_src3,
196 print_input(output, src3, swizzle.negate_src3, 191 SelectorToString(swizzle.src3_selector), true,
197 SelectorToString(swizzle.src3_selector), true, 192 src_is_inverted ? instr.mad.AddressRegisterName() : "");
198 instr.mad.AddressRegisterName());
199 } else {
200 print_input(output, src3, swizzle.negate_src3,
201 SelectorToString(swizzle.src3_selector));
202 }
203 AlignToColumn(kInputOperandColumnWidth); 193 AlignToColumn(kInputOperandColumnWidth);
204 break; 194 break;
205 } 195 }
@@ -222,16 +212,15 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
222 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); 212 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted);
223 print_input(output, src1, swizzle.negate_src1, 213 print_input(output, src1, swizzle.negate_src1,
224 swizzle.SelectorToString(false), true, 214 swizzle.SelectorToString(false), true,
225 instr.common.AddressRegisterName()); 215 src_is_inverted ? "" : instr.common.AddressRegisterName());
226 AlignToColumn(kInputOperandColumnWidth); 216 AlignToColumn(kInputOperandColumnWidth);
227 } 217 }
228 218
229 // TODO: In some cases, the Address Register is used as an index for SRC2
230 // instead of SRC1
231 if (opcode_info.subtype & OpCode::Info::Src2) { 219 if (opcode_info.subtype & OpCode::Info::Src2) {
232 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); 220 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted);
233 print_input(output, src2, swizzle.negate_src2, 221 print_input(output, src2, swizzle.negate_src2,
234 swizzle.SelectorToString(true)); 222 swizzle.SelectorToString(true), true,
223 src_is_inverted ? instr.common.AddressRegisterName() : "");
235 AlignToColumn(kInputOperandColumnWidth); 224 AlignToColumn(kInputOperandColumnWidth);
236 } 225 }
237 break; 226 break;
@@ -247,7 +236,9 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
247 236
248 switch (opcode.EffectiveOpCode()) { 237 switch (opcode.EffectiveOpCode()) {
249 case OpCode::Id::LOOP: 238 case OpCode::Id::LOOP:
250 output << "(unknown instruction format)"; 239 output << 'i' << instr.flow_control.int_uniform_id << " (end on 0x"
240 << std::setw(4) << std::right << std::setfill('0') << std::hex
241 << (4 * instr.flow_control.dest_offset) << ")";
251 break; 242 break;
252 243
253 default: 244 default:
@@ -255,7 +246,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
255 output << '('; 246 output << '(';
256 247
257 if (instr.flow_control.op != instr.flow_control.JustY) { 248 if (instr.flow_control.op != instr.flow_control.JustY) {
258 if (instr.flow_control.refx) 249 if (!instr.flow_control.refx)
259 output << '!'; 250 output << '!';
260 output << "cc.x"; 251 output << "cc.x";
261 } 252 }
@@ -267,13 +258,17 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
267 } 258 }
268 259
269 if (instr.flow_control.op != instr.flow_control.JustX) { 260 if (instr.flow_control.op != instr.flow_control.JustX) {
270 if (instr.flow_control.refy) 261 if (!instr.flow_control.refy)
271 output << '!'; 262 output << '!';
272 output << "cc.y"; 263 output << "cc.y";
273 } 264 }
274 265
275 output << ") "; 266 output << ") ";
276 } else if (opcode_info.subtype & OpCode::Info::HasUniformIndex) { 267 } else if (opcode_info.subtype & OpCode::Info::HasUniformIndex) {
268 if (opcode.EffectiveOpCode() == OpCode::Id::JMPU &&
269 (instr.flow_control.num_instructions & 1) == 1) {
270 output << '!';
271 }
277 output << 'b' << instr.flow_control.bool_uniform_id << ' '; 272 output << 'b' << instr.flow_control.bool_uniform_id << ' ';
278 } 273 }
279 274
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 922e5ab58..a7b66142f 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -149,7 +149,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
149 149
150 if (base_address == 0 && target_address == 0) { 150 if (base_address == 0 && target_address == 0) {
151 // Calculate the address at which to map the memory block. 151 // Calculate the address at which to map the memory block.
152 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address); 152 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address).value();
153 } 153 }
154 154
155 // Map the memory block into the target process 155 // Map the memory block into the target process
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index aad23e900..4e6b7b6f5 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -86,7 +86,7 @@ void GetSharedFont(Service::Interface* self) {
86 // The shared font has to be relocated to the new address before being passed to the 86 // The shared font has to be relocated to the new address before being passed to the
87 // application. 87 // application.
88 VAddr target_address = 88 VAddr target_address =
89 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); 89 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address).value();
90 if (!shared_font_relocated) { 90 if (!shared_font_relocated) {
91 BCFNT::RelocateSharedFont(shared_font_mem, target_address); 91 BCFNT::RelocateSharedFont(shared_font_mem, target_address);
92 shared_font_relocated = true; 92 shared_font_relocated = true;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index bc964ec60..88684b82d 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -475,12 +475,11 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
475 475
476 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever 476 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
477 // possible/likely 477 // possible/likely
478 Memory::RasterizerFlushRegion( 478 Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address,
479 Memory::VirtualToPhysicalAddress(command.dma_request.source_address), 479 command.dma_request.size, Memory::FlushMode::Flush);
480 command.dma_request.size); 480 Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address,
481 Memory::RasterizerFlushAndInvalidateRegion( 481 command.dma_request.size,
482 Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 482 Memory::FlushMode::FlushAndInvalidate);
483 command.dma_request.size);
484 483
485 // TODO(Subv): These memory accesses should not go through the application's memory mapping. 484 // TODO(Subv): These memory accesses should not go through the application's memory mapping.
486 // They should go through the GSP module's memory mapping. 485 // They should go through the GSP module's memory mapping.
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index e73971d5f..57172ddd6 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -587,8 +587,8 @@ static void StartConversion(Interface* self) {
587 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( 587 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
588 u32 total_output_size = 588 u32 total_output_size =
589 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); 589 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
590 Memory::RasterizerFlushAndInvalidateRegion( 590 Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size,
591 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); 591 Memory::FlushMode::FlushAndInvalidate);
592 592
593 HW::Y2R::PerformConversion(conversion); 593 HW::Y2R::PerformConversion(conversion);
594 594
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9024f4922..65649d9d7 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -83,19 +83,13 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
83 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, 83 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
84 (base + size) * PAGE_SIZE); 84 (base + size) * PAGE_SIZE);
85 85
86 u32 end = base + size; 86 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
87 FlushMode::FlushAndInvalidate);
87 88
89 u32 end = base + size;
88 while (base != end) { 90 while (base != end) {
89 ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base); 91 ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base);
90 92
91 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
92 // null here
93 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
94 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
95 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
96 PAGE_SIZE);
97 }
98
99 current_page_table->attributes[base] = type; 93 current_page_table->attributes[base] = type;
100 current_page_table->pointers[base] = memory; 94 current_page_table->pointers[base] = memory;
101 current_page_table->cached_res_count[base] = 0; 95 current_page_table->cached_res_count[base] = 0;
@@ -196,7 +190,7 @@ T Read(const VAddr vaddr) {
196 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 190 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
197 break; 191 break;
198 case PageType::RasterizerCachedMemory: { 192 case PageType::RasterizerCachedMemory: {
199 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 193 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
200 194
201 T value; 195 T value;
202 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); 196 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T));
@@ -205,8 +199,7 @@ T Read(const VAddr vaddr) {
205 case PageType::Special: 199 case PageType::Special:
206 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
207 case PageType::RasterizerCachedSpecial: { 201 case PageType::RasterizerCachedSpecial: {
208 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 202 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
209
210 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 203 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
211 } 204 }
212 default: 205 default:
@@ -236,8 +229,7 @@ void Write(const VAddr vaddr, const T data) {
236 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 229 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
237 break; 230 break;
238 case PageType::RasterizerCachedMemory: { 231 case PageType::RasterizerCachedMemory: {
239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 232 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
240
241 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 233 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
242 break; 234 break;
243 } 235 }
@@ -245,8 +237,7 @@ void Write(const VAddr vaddr, const T data) {
245 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 237 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
246 break; 238 break;
247 case PageType::RasterizerCachedSpecial: { 239 case PageType::RasterizerCachedSpecial: {
248 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 240 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
249
250 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
251 break; 242 break;
252 } 243 }
@@ -275,7 +266,8 @@ bool IsValidVirtualAddress(const VAddr vaddr) {
275} 266}
276 267
277bool IsValidPhysicalAddress(const PAddr paddr) { 268bool IsValidPhysicalAddress(const PAddr paddr) {
278 return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); 269 boost::optional<VAddr> vaddr = PhysicalToVirtualAddress(paddr);
270 return vaddr && IsValidVirtualAddress(*vaddr);
279} 271}
280 272
281u8* GetPointer(const VAddr vaddr) { 273u8* GetPointer(const VAddr vaddr) {
@@ -308,7 +300,8 @@ std::string ReadCString(VAddr vaddr, std::size_t max_length) {
308 300
309u8* GetPhysicalPointer(PAddr address) { 301u8* GetPhysicalPointer(PAddr address) {
310 // TODO(Subv): This call should not go through the application's memory mapping. 302 // TODO(Subv): This call should not go through the application's memory mapping.
311 return GetPointer(PhysicalToVirtualAddress(address)); 303 boost::optional<VAddr> vaddr = PhysicalToVirtualAddress(address);
304 return vaddr ? GetPointer(*vaddr) : nullptr;
312} 305}
313 306
314void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { 307void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
@@ -319,8 +312,12 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
319 u32 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; 312 u32 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1;
320 PAddr paddr = start; 313 PAddr paddr = start;
321 314
322 for (unsigned i = 0; i < num_pages; ++i) { 315 for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
323 VAddr vaddr = PhysicalToVirtualAddress(paddr); 316 boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
317 if (!maybe_vaddr)
318 continue;
319 VAddr vaddr = *maybe_vaddr;
320
324 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 321 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
325 ASSERT_MSG(count_delta <= UINT8_MAX - res_count, 322 ASSERT_MSG(count_delta <= UINT8_MAX - res_count,
326 "Rasterizer resource cache counter overflow!"); 323 "Rasterizer resource cache counter overflow!");
@@ -368,7 +365,6 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
368 UNREACHABLE(); 365 UNREACHABLE();
369 } 366 }
370 } 367 }
371 paddr += PAGE_SIZE;
372 } 368 }
373} 369}
374 370
@@ -379,11 +375,48 @@ void RasterizerFlushRegion(PAddr start, u32 size) {
379} 375}
380 376
381void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) { 377void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) {
378 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
379 // null here
382 if (VideoCore::g_renderer != nullptr) { 380 if (VideoCore::g_renderer != nullptr) {
383 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size); 381 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size);
384 } 382 }
385} 383}
386 384
385void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
386 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
387 // null here
388 if (VideoCore::g_renderer != nullptr) {
389 VAddr end = start + size;
390
391 auto CheckRegion = [&](VAddr region_start, VAddr region_end) {
392 if (start >= region_end || end <= region_start) {
393 // No overlap with region
394 return;
395 }
396
397 VAddr overlap_start = std::max(start, region_start);
398 VAddr overlap_end = std::min(end, region_end);
399
400 PAddr physical_start = TryVirtualToPhysicalAddress(overlap_start).value();
401 u32 overlap_size = overlap_end - overlap_start;
402
403 auto* rasterizer = VideoCore::g_renderer->Rasterizer();
404 switch (mode) {
405 case FlushMode::Flush:
406 rasterizer->FlushRegion(physical_start, overlap_size);
407 break;
408 case FlushMode::FlushAndInvalidate:
409 rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
410 break;
411 }
412 };
413
414 CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END);
415 CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END);
416 CheckRegion(VRAM_VADDR, VRAM_VADDR_END);
417 }
418}
419
387u8 Read8(const VAddr addr) { 420u8 Read8(const VAddr addr) {
388 return Read<u8>(addr); 421 return Read<u8>(addr);
389} 422}
@@ -430,16 +463,13 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
430 break; 463 break;
431 } 464 }
432 case PageType::RasterizerCachedMemory: { 465 case PageType::RasterizerCachedMemory: {
433 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 466 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
434
435 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); 467 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
436 break; 468 break;
437 } 469 }
438 case PageType::RasterizerCachedSpecial: { 470 case PageType::RasterizerCachedSpecial: {
439 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 471 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
440 472 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
441 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
442
443 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); 473 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
444 break; 474 break;
445 } 475 }
@@ -500,18 +530,13 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
500 break; 530 break;
501 } 531 }
502 case PageType::RasterizerCachedMemory: { 532 case PageType::RasterizerCachedMemory: {
503 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 533 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
504 copy_amount);
505
506 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 534 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
507 break; 535 break;
508 } 536 }
509 case PageType::RasterizerCachedSpecial: { 537 case PageType::RasterizerCachedSpecial: {
510 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 538 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
511 539 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
512 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
513 copy_amount);
514
515 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 540 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
516 break; 541 break;
517 } 542 }
@@ -557,18 +582,13 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
557 break; 582 break;
558 } 583 }
559 case PageType::RasterizerCachedMemory: { 584 case PageType::RasterizerCachedMemory: {
560 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 585 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
561 copy_amount);
562
563 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 586 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
564 break; 587 break;
565 } 588 }
566 case PageType::RasterizerCachedSpecial: { 589 case PageType::RasterizerCachedSpecial: {
567 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 590 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
568 591 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
569 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
570 copy_amount);
571
572 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 592 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
573 break; 593 break;
574 } 594 }
@@ -613,15 +633,13 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
613 break; 633 break;
614 } 634 }
615 case PageType::RasterizerCachedMemory: { 635 case PageType::RasterizerCachedMemory: {
616 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 636 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
617
618 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); 637 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
619 break; 638 break;
620 } 639 }
621 case PageType::RasterizerCachedSpecial: { 640 case PageType::RasterizerCachedSpecial: {
622 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 641 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
623 642 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
624 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
625 643
626 std::vector<u8> buffer(copy_amount); 644 std::vector<u8> buffer(copy_amount);
627 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); 645 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());
@@ -680,7 +698,7 @@ void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data)
680 mmio_handler->Write64(addr, data); 698 mmio_handler->Write64(addr, data);
681} 699}
682 700
683PAddr VirtualToPhysicalAddress(const VAddr addr) { 701boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
684 if (addr == 0) { 702 if (addr == 0) {
685 return 0; 703 return 0;
686 } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { 704 } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
@@ -697,12 +715,20 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) {
697 return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR; 715 return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR;
698 } 716 }
699 717
700 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); 718 return boost::none;
701 // To help with debugging, set bit on address so that it's obviously invalid. 719}
702 return addr | 0x80000000; 720
721PAddr VirtualToPhysicalAddress(const VAddr addr) {
722 auto paddr = TryVirtualToPhysicalAddress(addr);
723 if (!paddr) {
724 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr);
725 // To help with debugging, set bit on address so that it's obviously invalid.
726 return addr | 0x80000000;
727 }
728 return *paddr;
703} 729}
704 730
705VAddr PhysicalToVirtualAddress(const PAddr addr) { 731boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
706 if (addr == 0) { 732 if (addr == 0) {
707 return 0; 733 return 0;
708 } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { 734 } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
@@ -717,9 +743,7 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
717 return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR; 743 return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR;
718 } 744 }
719 745
720 LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr); 746 return boost::none;
721 // To help with debugging, set bit on address so that it's obviously invalid.
722 return addr | 0x80000000;
723} 747}
724 748
725} // namespace 749} // namespace
diff --git a/src/core/memory.h b/src/core/memory.h
index 71fb278ad..c8c56babd 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <string> 9#include <string>
10#include <boost/optional.hpp>
10#include "common/common_types.h" 11#include "common/common_types.h"
11 12
12namespace Memory { 13namespace Memory {
@@ -148,15 +149,23 @@ u8* GetPointer(VAddr virtual_address);
148std::string ReadCString(VAddr virtual_address, std::size_t max_length); 149std::string ReadCString(VAddr virtual_address, std::size_t max_length);
149 150
150/** 151/**
151* Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical 152 * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
152* address. This should be used by services to translate addresses for use by the hardware. 153 * address. This should be used by services to translate addresses for use by the hardware.
153*/ 154 */
155boost::optional<PAddr> TryVirtualToPhysicalAddress(VAddr addr);
156
157/**
158 * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
159 * address. This should be used by services to translate addresses for use by the hardware.
160 *
161 * @deprecated Use TryVirtualToPhysicalAddress(), which reports failure.
162 */
154PAddr VirtualToPhysicalAddress(VAddr addr); 163PAddr VirtualToPhysicalAddress(VAddr addr);
155 164
156/** 165/**
157* Undoes a mapping performed by VirtualToPhysicalAddress(). 166 * Undoes a mapping performed by VirtualToPhysicalAddress().
158*/ 167 */
159VAddr PhysicalToVirtualAddress(PAddr addr); 168boost::optional<VAddr> PhysicalToVirtualAddress(PAddr addr);
160 169
161/** 170/**
162 * Gets a pointer to the memory region beginning at the specified physical address. 171 * Gets a pointer to the memory region beginning at the specified physical address.
@@ -181,6 +190,19 @@ void RasterizerFlushRegion(PAddr start, u32 size);
181 */ 190 */
182void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 191void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
183 192
193enum class FlushMode {
194 /// Write back modified surfaces to RAM
195 Flush,
196 /// Write back modified surfaces to RAM, and also remove them from the cache
197 FlushAndInvalidate,
198};
199
200/**
201 * Flushes and invalidates any externally cached rasterizer resources touching the given virtual
202 * address region.
203 */
204void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
205
184/** 206/**
185 * Dynarmic has an optimization to memory accesses when the pointer to the page exists that 207 * Dynarmic has an optimization to memory accesses when the pointer to the page exists that
186 * can be used by setting up the current page table as a callback. This function is used to 208 * can be used by setting up the current page table as a callback. This function is used to
diff --git a/src/network/room.cpp b/src/network/room.cpp
index 8b7915bb7..fbbaf8b93 100644
--- a/src/network/room.cpp
+++ b/src/network/room.cpp
@@ -19,7 +19,7 @@ static constexpr u32 MaxConcurrentConnections = 10;
19class Room::RoomImpl { 19class Room::RoomImpl {
20public: 20public:
21 // This MAC address is used to generate a 'Nintendo' like Mac address. 21 // This MAC address is used to generate a 'Nintendo' like Mac address.
22 const MacAddress NintendoOUI = {0x00, 0x1F, 0x32, 0x00, 0x00, 0x00}; 22 const MacAddress NintendoOUI;
23 std::mt19937 random_gen; ///< Random number generator. Used for GenerateMacAddress 23 std::mt19937 random_gen; ///< Random number generator. Used for GenerateMacAddress
24 24
25 ENetHost* server = nullptr; ///< Network interface. 25 ENetHost* server = nullptr; ///< Network interface.
@@ -36,7 +36,8 @@ public:
36 using MemberList = std::vector<Member>; 36 using MemberList = std::vector<Member>;
37 MemberList members; ///< Information about the members of this room. 37 MemberList members; ///< Information about the members of this room.
38 38
39 RoomImpl() : random_gen(std::random_device()()) {} 39 RoomImpl()
40 : random_gen(std::random_device()()), NintendoOUI{0x00, 0x1F, 0x32, 0x00, 0x00, 0x00} {}
40 41
41 /// Thread that receives and dispatches network packets 42 /// Thread that receives and dispatches network packets
42 std::unique_ptr<std::thread> room_thread; 43 std::unique_ptr<std::thread> room_thread;
diff --git a/src/network/room.h b/src/network/room.h
index 54cccf0ae..65b0d008a 100644
--- a/src/network/room.h
+++ b/src/network/room.h
@@ -24,7 +24,7 @@ struct RoomInformation {
24using MacAddress = std::array<u8, 6>; 24using MacAddress = std::array<u8, 6>;
25/// A special MAC address that tells the room we're joining to assign us a MAC address 25/// A special MAC address that tells the room we're joining to assign us a MAC address
26/// automatically. 26/// automatically.
27const MacAddress NoPreferredMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 27constexpr MacAddress NoPreferredMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
28 28
29// 802.11 broadcast MAC address 29// 802.11 broadcast MAC address
30constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 30constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index ff3f69ba3..1c6c15a58 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -117,48 +117,53 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
117 117
118 // Setup the noise LUT for proctex 118 // Setup the noise LUT for proctex
119 proctex_noise_lut.Create(); 119 proctex_noise_lut.Create();
120 state.proctex_noise_lut.texture_1d = proctex_noise_lut.handle; 120 state.proctex_noise_lut.texture_buffer = proctex_noise_lut.handle;
121 state.Apply(); 121 state.Apply();
122 proctex_noise_lut_buffer.Create();
123 glBindBuffer(GL_TEXTURE_BUFFER, proctex_noise_lut_buffer.handle);
124 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW);
122 glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); 125 glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum());
123 glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); 126 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, proctex_noise_lut_buffer.handle);
124 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
125 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
126 127
127 // Setup the color map for proctex 128 // Setup the color map for proctex
128 proctex_color_map.Create(); 129 proctex_color_map.Create();
129 state.proctex_color_map.texture_1d = proctex_color_map.handle; 130 state.proctex_color_map.texture_buffer = proctex_color_map.handle;
130 state.Apply(); 131 state.Apply();
132 proctex_color_map_buffer.Create();
133 glBindBuffer(GL_TEXTURE_BUFFER, proctex_color_map_buffer.handle);
134 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW);
131 glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); 135 glActiveTexture(TextureUnits::ProcTexColorMap.Enum());
132 glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); 136 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, proctex_color_map_buffer.handle);
133 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
134 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
135 137
136 // Setup the alpha map for proctex 138 // Setup the alpha map for proctex
137 proctex_alpha_map.Create(); 139 proctex_alpha_map.Create();
138 state.proctex_alpha_map.texture_1d = proctex_alpha_map.handle; 140 state.proctex_alpha_map.texture_buffer = proctex_alpha_map.handle;
139 state.Apply(); 141 state.Apply();
142 proctex_alpha_map_buffer.Create();
143 glBindBuffer(GL_TEXTURE_BUFFER, proctex_alpha_map_buffer.handle);
144 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 2 * 128, nullptr, GL_DYNAMIC_DRAW);
140 glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); 145 glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum());
141 glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); 146 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, proctex_alpha_map_buffer.handle);
142 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
143 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
144 147
145 // Setup the LUT for proctex 148 // Setup the LUT for proctex
146 proctex_lut.Create(); 149 proctex_lut.Create();
147 state.proctex_lut.texture_1d = proctex_lut.handle; 150 state.proctex_lut.texture_buffer = proctex_lut.handle;
148 state.Apply(); 151 state.Apply();
152 proctex_lut_buffer.Create();
153 glBindBuffer(GL_TEXTURE_BUFFER, proctex_lut_buffer.handle);
154 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 4 * 256, nullptr, GL_DYNAMIC_DRAW);
149 glActiveTexture(TextureUnits::ProcTexLUT.Enum()); 155 glActiveTexture(TextureUnits::ProcTexLUT.Enum());
150 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); 156 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_lut_buffer.handle);
151 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
152 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
153 157
154 // Setup the difference LUT for proctex 158 // Setup the difference LUT for proctex
155 proctex_diff_lut.Create(); 159 proctex_diff_lut.Create();
156 state.proctex_diff_lut.texture_1d = proctex_diff_lut.handle; 160 state.proctex_diff_lut.texture_buffer = proctex_diff_lut.handle;
157 state.Apply(); 161 state.Apply();
162 proctex_diff_lut_buffer.Create();
163 glBindBuffer(GL_TEXTURE_BUFFER, proctex_diff_lut_buffer.handle);
164 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat) * 4 * 256, nullptr, GL_DYNAMIC_DRAW);
158 glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); 165 glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum());
159 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); 166 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, proctex_diff_lut_buffer.handle);
160 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
161 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
162 167
163 // Sync fixed function OpenGL state 168 // Sync fixed function OpenGL state
164 SyncCullMode(); 169 SyncCullMode();
@@ -1387,7 +1392,7 @@ void RasterizerOpenGL::SyncProcTexNoise() {
1387 1392
1388// helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap 1393// helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap
1389static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut, 1394static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut,
1390 std::array<GLvec2, 128>& lut_data, GLenum texture) { 1395 std::array<GLvec2, 128>& lut_data, GLuint buffer) {
1391 std::array<GLvec2, 128> new_data; 1396 std::array<GLvec2, 128> new_data;
1392 std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { 1397 std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) {
1393 return GLvec2{entry.ToFloat(), entry.DiffToFloat()}; 1398 return GLvec2{entry.ToFloat(), entry.DiffToFloat()};
@@ -1395,24 +1400,24 @@ static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntr
1395 1400
1396 if (new_data != lut_data) { 1401 if (new_data != lut_data) {
1397 lut_data = new_data; 1402 lut_data = new_data;
1398 glActiveTexture(texture); 1403 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
1399 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RG, GL_FLOAT, lut_data.data()); 1404 glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec2), new_data.data());
1400 } 1405 }
1401} 1406}
1402 1407
1403void RasterizerOpenGL::SyncProcTexNoiseLUT() { 1408void RasterizerOpenGL::SyncProcTexNoiseLUT() {
1404 SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, 1409 SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data,
1405 TextureUnits::ProcTexNoiseLUT.Enum()); 1410 proctex_noise_lut_buffer.handle);
1406} 1411}
1407 1412
1408void RasterizerOpenGL::SyncProcTexColorMap() { 1413void RasterizerOpenGL::SyncProcTexColorMap() {
1409 SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, 1414 SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data,
1410 TextureUnits::ProcTexColorMap.Enum()); 1415 proctex_color_map_buffer.handle);
1411} 1416}
1412 1417
1413void RasterizerOpenGL::SyncProcTexAlphaMap() { 1418void RasterizerOpenGL::SyncProcTexAlphaMap() {
1414 SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, 1419 SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data,
1415 TextureUnits::ProcTexAlphaMap.Enum()); 1420 proctex_alpha_map_buffer.handle);
1416} 1421}
1417 1422
1418void RasterizerOpenGL::SyncProcTexLUT() { 1423void RasterizerOpenGL::SyncProcTexLUT() {
@@ -1427,8 +1432,8 @@ void RasterizerOpenGL::SyncProcTexLUT() {
1427 1432
1428 if (new_data != proctex_lut_data) { 1433 if (new_data != proctex_lut_data) {
1429 proctex_lut_data = new_data; 1434 proctex_lut_data = new_data;
1430 glActiveTexture(TextureUnits::ProcTexLUT.Enum()); 1435 glBindBuffer(GL_TEXTURE_BUFFER, proctex_lut_buffer.handle);
1431 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_lut_data.data()); 1436 glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec4), new_data.data());
1432 } 1437 }
1433} 1438}
1434 1439
@@ -1444,8 +1449,8 @@ void RasterizerOpenGL::SyncProcTexDiffLUT() {
1444 1449
1445 if (new_data != proctex_diff_lut_data) { 1450 if (new_data != proctex_diff_lut_data) {
1446 proctex_diff_lut_data = new_data; 1451 proctex_diff_lut_data = new_data;
1447 glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); 1452 glBindBuffer(GL_TEXTURE_BUFFER, proctex_diff_lut_buffer.handle);
1448 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_diff_lut_data.data()); 1453 glBufferSubData(GL_TEXTURE_BUFFER, 0, new_data.size() * sizeof(GLvec4), new_data.data());
1449 } 1454 }
1450} 1455}
1451 1456
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index a433c1d4a..78e218efe 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -287,18 +287,23 @@ private:
287 OGLTexture fog_lut; 287 OGLTexture fog_lut;
288 std::array<GLvec2, 128> fog_lut_data{}; 288 std::array<GLvec2, 128> fog_lut_data{};
289 289
290 OGLBuffer proctex_noise_lut_buffer;
290 OGLTexture proctex_noise_lut; 291 OGLTexture proctex_noise_lut;
291 std::array<GLvec2, 128> proctex_noise_lut_data{}; 292 std::array<GLvec2, 128> proctex_noise_lut_data{};
292 293
294 OGLBuffer proctex_color_map_buffer;
293 OGLTexture proctex_color_map; 295 OGLTexture proctex_color_map;
294 std::array<GLvec2, 128> proctex_color_map_data{}; 296 std::array<GLvec2, 128> proctex_color_map_data{};
295 297
298 OGLBuffer proctex_alpha_map_buffer;
296 OGLTexture proctex_alpha_map; 299 OGLTexture proctex_alpha_map;
297 std::array<GLvec2, 128> proctex_alpha_map_data{}; 300 std::array<GLvec2, 128> proctex_alpha_map_data{};
298 301
302 OGLBuffer proctex_lut_buffer;
299 OGLTexture proctex_lut; 303 OGLTexture proctex_lut;
300 std::array<GLvec4, 256> proctex_lut_data{}; 304 std::array<GLvec4, 256> proctex_lut_data{};
301 305
306 OGLBuffer proctex_diff_lut_buffer;
302 OGLTexture proctex_diff_lut; 307 OGLTexture proctex_diff_lut;
303 std::array<GLvec4, 256> proctex_diff_lut_data{}; 308 std::array<GLvec4, 256> proctex_diff_lut_data{};
304}; 309};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 8b717e43d..f37894e7a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -542,10 +542,11 @@ RasterizerCacheOpenGL::GetFramebufferSurfaces(
542 config.GetDepthBufferPhysicalAddress(), 542 config.GetDepthBufferPhysicalAddress(),
543 fb_area * Pica::FramebufferRegs::BytesPerDepthPixel(config.depth_format)); 543 fb_area * Pica::FramebufferRegs::BytesPerDepthPixel(config.depth_format));
544 bool using_color_fb = config.GetColorBufferPhysicalAddress() != 0; 544 bool using_color_fb = config.GetColorBufferPhysicalAddress() != 0;
545 bool using_depth_fb = 545 bool depth_write_enable = regs.framebuffer.output_merger.depth_write_enable &&
546 config.GetDepthBufferPhysicalAddress() != 0 && 546 regs.framebuffer.framebuffer.allow_depth_stencil_write;
547 (regs.framebuffer.output_merger.depth_test_enable || 547 bool using_depth_fb = config.GetDepthBufferPhysicalAddress() != 0 &&
548 regs.framebuffer.output_merger.depth_write_enable || !framebuffers_overlap); 548 (regs.framebuffer.output_merger.depth_test_enable || depth_write_enable ||
549 !framebuffers_overlap);
549 550
550 if (framebuffers_overlap && using_color_fb && using_depth_fb) { 551 if (framebuffers_overlap && using_color_fb && using_depth_fb) {
551 LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " 552 LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; "
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index c93b108fb..bb192affd 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -886,12 +886,12 @@ void AppendProcTexSampler(std::string& out, const PicaShaderConfig& config) {
886 // coord=1.0 is lut[127]+lut_diff[127]. For other indices, the result is interpolated using 886 // coord=1.0 is lut[127]+lut_diff[127]. For other indices, the result is interpolated using
887 // value entries and difference entries. 887 // value entries and difference entries.
888 out += R"( 888 out += R"(
889float ProcTexLookupLUT(sampler1D lut, float coord) { 889float ProcTexLookupLUT(samplerBuffer lut, float coord) {
890 coord *= 128; 890 coord *= 128;
891 float index_i = clamp(floor(coord), 0.0, 127.0); 891 float index_i = clamp(floor(coord), 0.0, 127.0);
892 float index_f = coord - index_i; // fract() cannot be used here because 128.0 needs to be 892 float index_f = coord - index_i; // fract() cannot be used here because 128.0 needs to be
893 // extracted as index_i = 127.0 and index_f = 1.0 893 // extracted as index_i = 127.0 and index_f = 1.0
894 vec2 entry = texelFetch(lut, int(index_i), 0).rg; 894 vec2 entry = texelFetch(lut, int(index_i)).rg;
895 return clamp(entry.r + entry.g * index_f, 0.0, 1.0); 895 return clamp(entry.r + entry.g * index_f, 0.0, 1.0);
896} 896}
897 )"; 897 )";
@@ -979,14 +979,14 @@ float ProcTexNoiseCoef(vec2 x) {
979 out += "int lut_index_i = int(lut_coord) + " + 979 out += "int lut_index_i = int(lut_coord) + " +
980 std::to_string(config.state.proctex.lut_offset) + ";\n"; 980 std::to_string(config.state.proctex.lut_offset) + ";\n";
981 out += "float lut_index_f = fract(lut_coord);\n"; 981 out += "float lut_index_f = fract(lut_coord);\n";
982 out += "vec4 final_color = texelFetch(proctex_lut, lut_index_i, 0) + lut_index_f * " 982 out += "vec4 final_color = texelFetch(proctex_lut, lut_index_i) + lut_index_f * "
983 "texelFetch(proctex_diff_lut, lut_index_i, 0);\n"; 983 "texelFetch(proctex_diff_lut, lut_index_i);\n";
984 break; 984 break;
985 case ProcTexFilter::Nearest: 985 case ProcTexFilter::Nearest:
986 case ProcTexFilter::NearestMipmapLinear: 986 case ProcTexFilter::NearestMipmapLinear:
987 case ProcTexFilter::NearestMipmapNearest: 987 case ProcTexFilter::NearestMipmapNearest:
988 out += "lut_coord += " + std::to_string(config.state.proctex.lut_offset) + ";\n"; 988 out += "lut_coord += " + std::to_string(config.state.proctex.lut_offset) + ";\n";
989 out += "vec4 final_color = texelFetch(proctex_lut, int(round(lut_coord)), 0);\n"; 989 out += "vec4 final_color = texelFetch(proctex_lut, int(round(lut_coord)));\n";
990 break; 990 break;
991 } 991 }
992 992
@@ -1053,11 +1053,11 @@ layout (std140) uniform shader_data {
1053uniform sampler2D tex[3]; 1053uniform sampler2D tex[3];
1054uniform samplerBuffer lighting_lut; 1054uniform samplerBuffer lighting_lut;
1055uniform samplerBuffer fog_lut; 1055uniform samplerBuffer fog_lut;
1056uniform sampler1D proctex_noise_lut; 1056uniform samplerBuffer proctex_noise_lut;
1057uniform sampler1D proctex_color_map; 1057uniform samplerBuffer proctex_color_map;
1058uniform sampler1D proctex_alpha_map; 1058uniform samplerBuffer proctex_alpha_map;
1059uniform sampler1D proctex_lut; 1059uniform samplerBuffer proctex_lut;
1060uniform sampler1D proctex_diff_lut; 1060uniform samplerBuffer proctex_diff_lut;
1061 1061
1062// Rotate the vector v by the quaternion q 1062// Rotate the vector v by the quaternion q
1063vec3 quaternion_rotate(vec4 q, vec3 v) { 1063vec3 quaternion_rotate(vec4 q, vec3 v) {
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index eface2dea..bc9d34b84 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -56,11 +56,11 @@ OpenGLState::OpenGLState() {
56 56
57 fog_lut.texture_buffer = 0; 57 fog_lut.texture_buffer = 0;
58 58
59 proctex_lut.texture_1d = 0; 59 proctex_lut.texture_buffer = 0;
60 proctex_diff_lut.texture_1d = 0; 60 proctex_diff_lut.texture_buffer = 0;
61 proctex_color_map.texture_1d = 0; 61 proctex_color_map.texture_buffer = 0;
62 proctex_alpha_map.texture_1d = 0; 62 proctex_alpha_map.texture_buffer = 0;
63 proctex_noise_lut.texture_1d = 0; 63 proctex_noise_lut.texture_buffer = 0;
64 64
65 draw.read_framebuffer = 0; 65 draw.read_framebuffer = 0;
66 draw.draw_framebuffer = 0; 66 draw.draw_framebuffer = 0;
@@ -204,33 +204,33 @@ void OpenGLState::Apply() const {
204 } 204 }
205 205
206 // ProcTex Noise LUT 206 // ProcTex Noise LUT
207 if (proctex_noise_lut.texture_1d != cur_state.proctex_noise_lut.texture_1d) { 207 if (proctex_noise_lut.texture_buffer != cur_state.proctex_noise_lut.texture_buffer) {
208 glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); 208 glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum());
209 glBindTexture(GL_TEXTURE_1D, proctex_noise_lut.texture_1d); 209 glBindTexture(GL_TEXTURE_BUFFER, proctex_noise_lut.texture_buffer);
210 } 210 }
211 211
212 // ProcTex Color Map 212 // ProcTex Color Map
213 if (proctex_color_map.texture_1d != cur_state.proctex_color_map.texture_1d) { 213 if (proctex_color_map.texture_buffer != cur_state.proctex_color_map.texture_buffer) {
214 glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); 214 glActiveTexture(TextureUnits::ProcTexColorMap.Enum());
215 glBindTexture(GL_TEXTURE_1D, proctex_color_map.texture_1d); 215 glBindTexture(GL_TEXTURE_BUFFER, proctex_color_map.texture_buffer);
216 } 216 }
217 217
218 // ProcTex Alpha Map 218 // ProcTex Alpha Map
219 if (proctex_alpha_map.texture_1d != cur_state.proctex_alpha_map.texture_1d) { 219 if (proctex_alpha_map.texture_buffer != cur_state.proctex_alpha_map.texture_buffer) {
220 glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); 220 glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum());
221 glBindTexture(GL_TEXTURE_1D, proctex_alpha_map.texture_1d); 221 glBindTexture(GL_TEXTURE_BUFFER, proctex_alpha_map.texture_buffer);
222 } 222 }
223 223
224 // ProcTex LUT 224 // ProcTex LUT
225 if (proctex_lut.texture_1d != cur_state.proctex_lut.texture_1d) { 225 if (proctex_lut.texture_buffer != cur_state.proctex_lut.texture_buffer) {
226 glActiveTexture(TextureUnits::ProcTexLUT.Enum()); 226 glActiveTexture(TextureUnits::ProcTexLUT.Enum());
227 glBindTexture(GL_TEXTURE_1D, proctex_lut.texture_1d); 227 glBindTexture(GL_TEXTURE_BUFFER, proctex_lut.texture_buffer);
228 } 228 }
229 229
230 // ProcTex Diff LUT 230 // ProcTex Diff LUT
231 if (proctex_diff_lut.texture_1d != cur_state.proctex_diff_lut.texture_1d) { 231 if (proctex_diff_lut.texture_buffer != cur_state.proctex_diff_lut.texture_buffer) {
232 glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); 232 glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum());
233 glBindTexture(GL_TEXTURE_1D, proctex_diff_lut.texture_1d); 233 glBindTexture(GL_TEXTURE_BUFFER, proctex_diff_lut.texture_buffer);
234 } 234 }
235 235
236 // Framebuffer 236 // Framebuffer
@@ -274,16 +274,16 @@ void OpenGLState::ResetTexture(GLuint handle) {
274 cur_state.lighting_lut.texture_buffer = 0; 274 cur_state.lighting_lut.texture_buffer = 0;
275 if (cur_state.fog_lut.texture_buffer == handle) 275 if (cur_state.fog_lut.texture_buffer == handle)
276 cur_state.fog_lut.texture_buffer = 0; 276 cur_state.fog_lut.texture_buffer = 0;
277 if (cur_state.proctex_noise_lut.texture_1d == handle) 277 if (cur_state.proctex_noise_lut.texture_buffer == handle)
278 cur_state.proctex_noise_lut.texture_1d = 0; 278 cur_state.proctex_noise_lut.texture_buffer = 0;
279 if (cur_state.proctex_color_map.texture_1d == handle) 279 if (cur_state.proctex_color_map.texture_buffer == handle)
280 cur_state.proctex_color_map.texture_1d = 0; 280 cur_state.proctex_color_map.texture_buffer = 0;
281 if (cur_state.proctex_alpha_map.texture_1d == handle) 281 if (cur_state.proctex_alpha_map.texture_buffer == handle)
282 cur_state.proctex_alpha_map.texture_1d = 0; 282 cur_state.proctex_alpha_map.texture_buffer = 0;
283 if (cur_state.proctex_lut.texture_1d == handle) 283 if (cur_state.proctex_lut.texture_buffer == handle)
284 cur_state.proctex_lut.texture_1d = 0; 284 cur_state.proctex_lut.texture_buffer = 0;
285 if (cur_state.proctex_diff_lut.texture_1d == handle) 285 if (cur_state.proctex_diff_lut.texture_buffer == handle)
286 cur_state.proctex_diff_lut.texture_1d = 0; 286 cur_state.proctex_diff_lut.texture_buffer = 0;
287} 287}
288 288
289void OpenGLState::ResetSampler(GLuint handle) { 289void OpenGLState::ResetSampler(GLuint handle) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 1efcf0811..745a74479 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -95,23 +95,23 @@ public:
95 } fog_lut; 95 } fog_lut;
96 96
97 struct { 97 struct {
98 GLuint texture_1d; // GL_TEXTURE_BINDING_1D 98 GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
99 } proctex_noise_lut; 99 } proctex_noise_lut;
100 100
101 struct { 101 struct {
102 GLuint texture_1d; // GL_TEXTURE_BINDING_1D 102 GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
103 } proctex_color_map; 103 } proctex_color_map;
104 104
105 struct { 105 struct {
106 GLuint texture_1d; // GL_TEXTURE_BINDING_1D 106 GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
107 } proctex_alpha_map; 107 } proctex_alpha_map;
108 108
109 struct { 109 struct {
110 GLuint texture_1d; // GL_TEXTURE_BINDING_1D 110 GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
111 } proctex_lut; 111 } proctex_lut;
112 112
113 struct { 113 struct {
114 GLuint texture_1d; // GL_TEXTURE_BINDING_1D 114 GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER
115 } proctex_diff_lut; 115 } proctex_diff_lut;
116 116
117 struct { 117 struct {