VideoCore: Implement DispatchIndirect

This commit is contained in:
Fernando Sahmkow
2023-08-27 02:58:00 +02:00
parent 710ca3ca49
commit 115792158d
11 changed files with 119 additions and 13 deletions

View File

@ -11,6 +11,14 @@
namespace Tegra::Engines {
enum class EngineTypes : u32 {
KeplerCompute,
Maxwell3D,
Fermi2D,
MaxwellDMA,
KeplerMemory,
};
class EngineInterface {
public:
virtual ~EngineInterface() = default;

View File

@ -69,6 +69,14 @@ public:
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
GPUVAddr ExecTargetAddress() const {
return regs.dest.Address();
}
u32 GetUploadSize() const {
return copy_size;
}
private:
void ProcessData(std::span<const u8> read_buffer);

View File

@ -43,16 +43,33 @@ void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_cal
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
UploadInfo info{.upload_address = upload_address,
.exec_address = upload_state.ExecTargetAddress(),
.copy_size = upload_state.GetUploadSize()};
uploads.push_back(info);
upload_state.ProcessExec(regs.exec_upload.linear != 0);
break;
}
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
upload_address = current_dma_segment;
upload_state.ProcessData(method_argument, is_last_call);
break;
}
case KEPLER_COMPUTE_REG_INDEX(launch):
case KEPLER_COMPUTE_REG_INDEX(launch): {
const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address();
for (auto& data : uploads) {
const GPUVAddr offset = data.exec_address - launch_desc_loc;
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x) &&
memory_manager.IsMemoryDirty(data.upload_address, data.copy_size)) {
indirect_compute = {data.upload_address};
}
}
uploads.clear();
ProcessLaunch();
indirect_compute = std::nullopt;
break;
}
default:
break;
}
@ -62,6 +79,7 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun
u32 methods_pending) {
switch (method) {
case KEPLER_COMPUTE_REG_INDEX(data_upload):
upload_address = current_dma_segment;
upload_state.ProcessData(base_start, amount);
return;
default:

View File

@ -5,6 +5,7 @@
#include <array>
#include <cstddef>
#include <optional>
#include <vector>
#include "common/bit_field.h"
#include "common/common_funcs.h"
@ -36,6 +37,9 @@ namespace Tegra::Engines {
#define KEPLER_COMPUTE_REG_INDEX(field_name) \
(offsetof(Tegra::Engines::KeplerCompute::Regs, field_name) / sizeof(u32))
#define LAUNCH_REG_INDEX(field_name) \
(offsetof(Tegra::Engines::KeplerCompute::LaunchParams, field_name) / sizeof(u32))
class KeplerCompute final : public EngineInterface {
public:
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
@ -201,6 +205,10 @@ public:
void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
u32 methods_pending) override;
std::optional<GPUVAddr> GetIndirectComputeAddress() const {
return indirect_compute;
}
private:
void ProcessLaunch();
@ -216,6 +224,15 @@ private:
MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state;
GPUVAddr upload_address;
struct UploadInfo {
GPUVAddr upload_address;
GPUVAddr exec_address;
u32 copy_size;
};
std::vector<UploadInfo> uploads;
std::optional<GPUVAddr> indirect_compute{};
};
#define ASSERT_REG_POSITION(field_name, position) \

View File

@ -34,19 +34,24 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) {
bound_engines[method_call.subchannel] = engine_id;
switch (engine_id) {
case EngineID::FERMI_TWOD_A:
dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel);
dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel,
EngineTypes::Fermi2D);
break;
case EngineID::MAXWELL_B:
dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel);
dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel,
EngineTypes::Maxwell3D);
break;
case EngineID::KEPLER_COMPUTE_B:
dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel);
dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel,
EngineTypes::KeplerCompute);
break;
case EngineID::MAXWELL_DMA_COPY_A:
dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel);
dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel,
EngineTypes::MaxwellDMA);
break;
case EngineID::KEPLER_INLINE_TO_MEMORY_B:
dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel);
dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel,
EngineTypes::KeplerMemory);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id);