mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-11 08:57:57 -05:00
VideoCore: Implement DispatchIndirect
This commit is contained in:
@ -11,6 +11,14 @@
|
||||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
enum class EngineTypes : u32 {
|
||||
KeplerCompute,
|
||||
Maxwell3D,
|
||||
Fermi2D,
|
||||
MaxwellDMA,
|
||||
KeplerMemory,
|
||||
};
|
||||
|
||||
class EngineInterface {
|
||||
public:
|
||||
virtual ~EngineInterface() = default;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user