From 5119a5761429477079491795d5d9d1bd335f7b0b Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Mon, 14 Mar 2022 19:11:41 -0400 Subject: 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. --- src/video_core/engines/maxwell_3d.cpp | 67 ++++++----------------------------- src/video_core/engines/maxwell_3d.h | 15 +------- 2 files changed, 12 insertions(+), 70 deletions(-) (limited to 'src/video_core') 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 case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13: case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14: case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15: - return StartCBData(method); + return ProcessCBData(argument); case MAXWELL3D_REG_INDEX(cb_bind[0]): return ProcessCBBind(0); case MAXWELL3D_REG_INDEX(cb_bind[1]): @@ -248,14 +248,6 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) } void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { - if (method == cb_data_state.current) { - regs.reg_array[method] = method_argument; - ProcessCBData(method_argument); - return; - } else if (cb_data_state.current != null_cb_data) { - FinishCBData(); - } - // It is an error to write to a register other than the current macro's ARG register before it // has finished execution. if (executing_macro != 0) { @@ -302,7 +294,7 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 13: case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 14: case MAXWELL3D_REG_INDEX(const_buffer.cb_data) + 15: - ProcessCBMultiData(method, base_start, amount); + ProcessCBMultiData(base_start, amount); break; default: for (std::size_t i = 0; i < amount; i++) { @@ -587,46 +579,7 @@ void Maxwell3D::ProcessCBBind(size_t stage_index) { rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size); } -void Maxwell3D::ProcessCBData(u32 value) { - const u32 id = cb_data_state.id; - cb_data_state.buffer[id][cb_data_state.counter] = value; - // Increment the current buffer position. - regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; - cb_data_state.counter++; -} - -void Maxwell3D::StartCBData(u32 method) { - constexpr u32 first_cb_data = MAXWELL3D_REG_INDEX(const_buffer.cb_data); - cb_data_state.start_pos = regs.const_buffer.cb_pos; - cb_data_state.id = method - first_cb_data; - cb_data_state.current = method; - cb_data_state.counter = 0; - ProcessCBData(regs.const_buffer.cb_data[cb_data_state.id]); -} - -void Maxwell3D::ProcessCBMultiData(u32 method, const u32* start_base, u32 amount) { - if (cb_data_state.current != method) { - if (cb_data_state.current != null_cb_data) { - FinishCBData(); - } - constexpr u32 first_cb_data = MAXWELL3D_REG_INDEX(const_buffer.cb_data); - cb_data_state.start_pos = regs.const_buffer.cb_pos; - cb_data_state.id = method - first_cb_data; - cb_data_state.current = method; - cb_data_state.counter = 0; - } - const std::size_t id = cb_data_state.id; - const std::size_t size = amount; - std::size_t i = 0; - for (; i < size; i++) { - cb_data_state.buffer[id][cb_data_state.counter] = start_base[i]; - cb_data_state.counter++; - } - // Increment the current buffer position. - regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4 * amount; -} - -void Maxwell3D::FinishCBData() { +void Maxwell3D::ProcessCBMultiData(const u32* start_base, u32 amount) { // Write the input value to the current const buffer at the current position. const GPUVAddr buffer_address = regs.const_buffer.BufferAddress(); ASSERT(buffer_address != 0); @@ -634,14 +587,16 @@ void Maxwell3D::FinishCBData() { // Don't allow writing past the end of the buffer. ASSERT(regs.const_buffer.cb_pos <= regs.const_buffer.cb_size); - const GPUVAddr address{buffer_address + cb_data_state.start_pos}; - const std::size_t size = regs.const_buffer.cb_pos - cb_data_state.start_pos; + const GPUVAddr address{buffer_address + regs.const_buffer.cb_pos}; + const size_t copy_size = amount * sizeof(u32); + memory_manager.WriteBlock(address, start_base, copy_size); - const u32 id = cb_data_state.id; - memory_manager.WriteBlock(address, cb_data_state.buffer[id].data(), size); + // Increment the current buffer position. + regs.const_buffer.cb_pos += static_cast(copy_size); +} - cb_data_state.id = null_cb_data; - cb_data_state.current = null_cb_data; +void Maxwell3D::ProcessCBData(u32 value) { + ProcessCBMultiData(&value, 1); } Texture::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: void ProcessSyncPoint(); /// Handles a write to the CB_DATA[i] register. - void StartCBData(u32 method); void ProcessCBData(u32 value); - void ProcessCBMultiData(u32 method, const u32* start_base, u32 amount); - void FinishCBData(); + void ProcessCBMultiData(const u32* start_base, u32 amount); /// Handles a write to the CB_BIND register. void ProcessCBBind(size_t stage_index); @@ -1555,17 +1553,6 @@ private: /// Interpreter for the macro codes uploaded to the GPU. std::unique_ptr macro_engine; - static constexpr u32 null_cb_data = 0xFFFFFFFF; - struct CBDataState { - static constexpr size_t inline_size = 0x4000; - std::array, 16> buffer; - u32 current{null_cb_data}; - u32 id{null_cb_data}; - u32 start_pos{}; - u32 counter{}; - }; - CBDataState cb_data_state; - Upload::State upload_state; bool execute_on{true}; -- cgit v1.2.3