summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ameerj2022-03-14 19:11:41 -0400
committerGravatar ameerj2022-03-14 19:18:36 -0400
commit5119a5761429477079491795d5d9d1bd335f7b0b (patch)
tree2a2ba54451fb35260c1e0e797a3bbc5b96fe3316
parentMerge pull request #8016 from merryhime/kill-mem-use (diff)
downloadyuzu-5119a5761429477079491795d5d9d1bd335f7b0b.tar.gz
yuzu-5119a5761429477079491795d5d9d1bd335f7b0b.tar.xz
yuzu-5119a5761429477079491795d5d9d1bd335f7b0b.zip
maxwell_3d: Implement a safer CB data upload
This makes constant buffer uploads safer and more accurate by updating the GPU memory as soon as the CB Data method is invoked. The previous implementation was deferring the updates until a different maxwell 3d method was detected, then writing all CB data at once.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp67
-rw-r--r--src/video_core/engines/maxwell_3d.h15
2 files changed, 12 insertions, 70 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5d6d217bb..ba19d1ca2 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -195,7 +195,7 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
195 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13: 195 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
196 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14: 196 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
197 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15: 197 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
198 return StartCBData(method); 198 return ProcessCBData(argument);
199 case MAXWELL3D_REG_INDEX(cb_bind[0]): 199 case MAXWELL3D_REG_INDEX(cb_bind[0]):
200 return ProcessCBBind(0); 200 return ProcessCBBind(0);
201 case MAXWELL3D_REG_INDEX(cb_bind[1]): 201 case MAXWELL3D_REG_INDEX(cb_bind[1]):
@@ -248,14 +248,6 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters)
248} 248}
249 249
250void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 250void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
251 if (method == cb_data_state.current) {
252 regs.reg_array[method] = method_argument;
253 ProcessCBData(method_argument);
254 return;
255 } else if (cb_data_state.current != null_cb_data) {
256 FinishCBData();
257 }
258
259 // It is an error to write to a register other than the current macro's ARG register before it 251 // It is an error to write to a register other than the current macro's ARG register before it
260 // has finished execution. 252 // has finished execution.
261 if (executing_macro != 0) { 253 if (executing_macro != 0) {
@@ -302,7 +294,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
302 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13: 294 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13:
303 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14: 295 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14:
304 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15: 296 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15:
305 ProcessCBMultiData(method, base_start, amount); 297 ProcessCBMultiData(base_start, amount);
306 break; 298 break;
307 default: 299 default:
308 for (std::size_t i = 0; i < amount; i++) { 300 for (std::size_t i = 0; i < amount; i++) {
@@ -587,46 +579,7 @@ void Maxwell3D::ProcessCBBind(size_t stage_index) {
587 rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size); 579 rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size);
588} 580}
589 581
590void Maxwell3D::ProcessCBData(u32 value) { 582void Maxwell3D::ProcessCBMultiData(const u32* start_base, u32 amount) {
591 const u32 id = cb_data_state.id;
592 cb_data_state.buffer[id][cb_data_state.counter] = value;
593 // Increment the current buffer position.
594 regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4;
595 cb_data_state.counter++;
596}
597
598void Maxwell3D::StartCBData(u32 method) {
599 constexpr u32 first_cb_data = MAXWELL3D_REG_INDEX(const_buffer.cb_data);
600 cb_data_state.start_pos = regs.const_buffer.cb_pos;
601 cb_data_state.id = method - first_cb_data;
602 cb_data_state.current = method;
603 cb_data_state.counter = 0;
604 ProcessCBData(regs.const_buffer.cb_data[cb_data_state.id]);
605}
606
607void Maxwell3D::ProcessCBMultiData(u32 method, const u32* start_base, u32 amount) {
608 if (cb_data_state.current != method) {
609 if (cb_data_state.current != null_cb_data) {
610 FinishCBData();
611 }
612 constexpr u32 first_cb_data = MAXWELL3D_REG_INDEX(const_buffer.cb_data);
613 cb_data_state.start_pos = regs.const_buffer.cb_pos;
614 cb_data_state.id = method - first_cb_data;
615 cb_data_state.current = method;
616 cb_data_state.counter = 0;
617 }
618 const std::size_t id = cb_data_state.id;
619 const std::size_t size = amount;
620 std::size_t i = 0;
621 for (; i < size; i++) {
622 cb_data_state.buffer[id][cb_data_state.counter] = start_base[i];
623 cb_data_state.counter++;
624 }
625 // Increment the current buffer position.
626 regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4 * amount;
627}
628
629void Maxwell3D::FinishCBData() {
630 // Write the input value to the current const buffer at the current position. 583 // Write the input value to the current const buffer at the current position.
631 const GPUVAddr buffer_address = regs.const_buffer.BufferAddress(); 584 const GPUVAddr buffer_address = regs.const_buffer.BufferAddress();
632 ASSERT(buffer_address != 0); 585 ASSERT(buffer_address != 0);
@@ -634,14 +587,16 @@ void Maxwell3D::FinishCBData() {
634 // Don't allow writing past the end of the buffer. 587 // Don't allow writing past the end of the buffer.
635 ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size); 588 ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size);
636 589
637 const GPUVAddr address{buffer_address + cb_data_state.start_pos}; 590 const GPUVAddr address{buffer_address + regs.const_buffer.cb_pos};
638 const std::size_t size = regs.const_buffer.cb_pos - cb_data_state.start_pos; 591 const size_t copy_size = amount * sizeof(u32);
592 memory_manager.WriteBlock(address, start_base, copy_size);
639 593
640 const u32 id = cb_data_state.id; 594 // Increment the current buffer position.
641 memory_manager.WriteBlock(address, cb_data_state.buffer[id].data(), size); 595 regs.const_buffer.cb_pos += static_cast<u32>(copy_size);
596}
642 597
643 cb_data_state.id = null_cb_data; 598void Maxwell3D::ProcessCBData(u32 value) {
644 cb_data_state.current = null_cb_data; 599 ProcessCBMultiData(&value, 1);
645} 600}
646 601
647Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const { 602Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index dc9df6c8b..38d9b6660 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1520,10 +1520,8 @@ private:
1520 void ProcessSyncPoint(); 1520 void ProcessSyncPoint();
1521 1521
1522 /// Handles a write to the CB_DATA[i] register. 1522 /// Handles a write to the CB_DATA[i] register.
1523 void StartCBData(u32 method);
1524 void ProcessCBData(u32 value); 1523 void ProcessCBData(u32 value);
1525 void ProcessCBMultiData(u32 method, const u32* start_base, u32 amount); 1524 void ProcessCBMultiData(const u32* start_base, u32 amount);
1526 void FinishCBData();
1527 1525
1528 /// Handles a write to the CB_BIND register. 1526 /// Handles a write to the CB_BIND register.
1529 void ProcessCBBind(size_t stage_index); 1527 void ProcessCBBind(size_t stage_index);
@@ -1555,17 +1553,6 @@ private:
1555 /// Interpreter for the macro codes uploaded to the GPU. 1553 /// Interpreter for the macro codes uploaded to the GPU.
1556 std::unique_ptr<MacroEngine> macro_engine; 1554 std::unique_ptr<MacroEngine> macro_engine;
1557 1555
1558 static constexpr u32 null_cb_data = 0xFFFFFFFF;
1559 struct CBDataState {
1560 static constexpr size_t inline_size = 0x4000;
1561 std::array<std::array<u32, inline_size>, 16> buffer;
1562 u32 current{null_cb_data};
1563 u32 id{null_cb_data};
1564 u32 start_pos{};
1565 u32 counter{};
1566 };
1567 CBDataState cb_data_state;
1568
1569 Upload::State upload_state; 1556 Upload::State upload_state;
1570 1557
1571 bool execute_on{true}; 1558 bool execute_on{true};