kernel: Module loading

This commit is contained in:
raphaelthegreat 2024-06-04 22:03:18 +03:00
parent 611745170e
commit 48a158f18a
21 changed files with 155 additions and 41 deletions

View File

@ -52,7 +52,6 @@ std::string MntPoints::GetHostFile(const std::string& guest_file) {
if (find == 0) { if (find == 0) {
std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1); std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1);
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
fmt::print("GetHostFile: {}\n", pair.host_path + npath);
return pair.host_path + npath; return pair.host_path + npath;
} }
} }

View File

@ -236,13 +236,42 @@ size_t PS4_SYSV_ABI sceKernelPread(int fd, void *buf, size_t count, uint64_t off
return file.ReadRaw<u8>(buf, count); return file.ReadRaw<u8>(buf, count);
} }
int PS4_SYSV_ABI Unknown1() { s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char *moduleFileName, size_t args, const void *argp,
return 0x81100004; u32 flags, const void *pOpt, int *pRes) {
LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args);
if (flags != 0) {
return 0x80020016;
}
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto path = mnt->GetHostFile(moduleFileName);
// Load PRX module.
auto* linker = Common::Singleton<Core::Linker>::Instance();
u32 handle = linker->LoadModule(path);
auto* module = linker->GetModule(handle);
linker->Relocate(module);
// Retrieve and verify proc param according to libkernel.
const u64* param = module->GetProcParam<u64*>();
ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]);
module->Start(args, argp, 0);
return handle;
}
s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char *symbol, void **addrp) {
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->GetModule(handle);
*addrp = module->FindByName(symbol);
if (*addrp == nullptr) {
return 0x80020003;
}
return ORBIS_OK;
} }
void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("fJgP+wqifno", "libSceDiscMap", 1, "libSceDiscMap", 1, 1, Unknown1);
// obj // obj
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
// memory // memory
@ -260,6 +289,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory); LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory);
LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery); LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery);
LIB_FUNCTION("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI); LIB_FUNCTION("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI);
LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", 1, 1, sceKernelLoadStartModule);
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
// equeue // equeue
LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue); LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue);

View File

@ -94,23 +94,22 @@ void Linker::Execute() {
} }
} }
Module* Linker::LoadModule(const std::filesystem::path& elf_name) { s32 Linker::LoadModule(const std::filesystem::path& elf_name) {
std::scoped_lock lk{mutex};
if (!std::filesystem::exists(elf_name)) { if (!std::filesystem::exists(elf_name)) {
LOG_ERROR(Core_Linker, "Provided file {} does not exist", elf_name.string()); LOG_ERROR(Core_Linker, "Provided file {} does not exist", elf_name.string());
return nullptr; return -1;
} }
auto module = std::make_unique<Module>(elf_name); auto module = std::make_unique<Module>(elf_name);
if (!module->IsValid()) { if (!module->IsValid()) {
LOG_ERROR(Core_Linker, "Provided file {} is not valid ELF file", elf_name.string()); LOG_ERROR(Core_Linker, "Provided file {} is not valid ELF file", elf_name.string());
return nullptr; return -1;
} }
if (!module->IsSharedLib()) { m_modules.emplace_back(std::move(module));
main_proc_param_addr = module->GetProcParam(); return m_modules.size() - 1;
}
return m_modules.emplace_back(std::move(module)).get();
} }
void Linker::Relocate(Module* module) { void Linker::Relocate(Module* module) {

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <mutex>
#include <vector> #include <vector>
#include "core/module.h" #include "core/module.h"
@ -29,7 +30,11 @@ public:
} }
VAddr GetProcParam() const { VAddr GetProcParam() const {
return main_proc_param_addr; return m_modules[0]->GetProcParam();
}
Module* GetModule(s32 index) const {
return m_modules.at(index).get();
} }
void SetHeapApiFunc(void* func) { void SetHeapApiFunc(void* func) {
@ -39,7 +44,7 @@ public:
void* TlsGetAddr(u64 module_index, u64 offset); void* TlsGetAddr(u64 module_index, u64 offset);
void InitTlsForThread(bool is_primary = false); void InitTlsForThread(bool is_primary = false);
Module* LoadModule(const std::filesystem::path& elf_name); s32 LoadModule(const std::filesystem::path& elf_name);
void Relocate(Module* module); void Relocate(Module* module);
void Resolve(const std::string& name, Loader::SymbolType type, void Resolve(const std::string& name, Loader::SymbolType type,
@ -49,15 +54,14 @@ public:
private: private:
const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l);
void InitTls();
std::mutex mutex;
u32 dtv_generation_counter{1}; u32 dtv_generation_counter{1};
size_t static_tls_size{}; size_t static_tls_size{};
size_t max_tls_index{}; size_t max_tls_index{};
HeapApiFunc heap_api_func{}; HeapApiFunc heap_api_func{};
std::vector<std::unique_ptr<Module>> m_modules; std::vector<std::unique_ptr<Module>> m_modules;
Loader::SymbolsResolver m_hle_symbols{}; Loader::SymbolsResolver m_hle_symbols{};
VAddr main_proc_param_addr{};
}; };
} // namespace Core } // namespace Core

View File

@ -11,7 +11,7 @@
namespace Core::Loader { namespace Core::Loader {
void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) { void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) {
m_symbols.emplace_back(GenerateName(s), virtual_addr); m_symbols.emplace_back(GenerateName(s), s.nidName, virtual_addr);
} }
std::string SymbolsResolver::GenerateName(const SymbolResolver& s) { std::string SymbolsResolver::GenerateName(const SymbolResolver& s) {

View File

@ -6,6 +6,7 @@
#include <filesystem> #include <filesystem>
#include <string> #include <string>
#include <vector> #include <vector>
#include <span>
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {
@ -20,6 +21,7 @@ enum class SymbolType {
struct SymbolRecord { struct SymbolRecord {
std::string name; std::string name;
std::string nid_name;
u64 virtual_address; u64 virtual_address;
}; };
@ -42,6 +44,10 @@ public:
void AddSymbol(const SymbolResolver& s, u64 virtual_addr); void AddSymbol(const SymbolResolver& s, u64 virtual_addr);
const SymbolRecord* FindSymbol(const SymbolResolver& s) const; const SymbolRecord* FindSymbol(const SymbolResolver& s) const;
std::span<const SymbolRecord> GetSymbols() const {
return m_symbols;
}
size_t GetSize() const noexcept { size_t GetSize() const noexcept {
return m_symbols.size(); return m_symbols.size();
} }

View File

@ -240,7 +240,7 @@ MemoryManager::VMAHandle MemoryManager::MergeAdjacent(VMAHandle iter) {
} }
void MemoryManager::MapVulkanMemory(VAddr addr, size_t size) { void MemoryManager::MapVulkanMemory(VAddr addr, size_t size) {
return; //return;
const vk::Device device = instance->GetDevice(); const vk::Device device = instance->GetDevice();
const auto memory_props = instance->GetPhysicalDevice().getMemoryProperties(); const auto memory_props = instance->GetPhysicalDevice().getMemoryProperties();
void* host_pointer = reinterpret_cast<void*>(addr); void* host_pointer = reinterpret_cast<void*>(addr);
@ -312,7 +312,7 @@ void MemoryManager::MapVulkanMemory(VAddr addr, size_t size) {
} }
void MemoryManager::UnmapVulkanMemory(VAddr addr, size_t size) { void MemoryManager::UnmapVulkanMemory(VAddr addr, size_t size) {
return; //return;
const auto it = mapped_memories.find(addr); const auto it = mapped_memories.find(addr);
ASSERT(it != mapped_memories.end() && it->second.buffer_size == size); ASSERT(it != mapped_memories.end() && it->second.buffer_size == size);
mapped_memories.erase(it); mapped_memories.erase(it);

View File

@ -349,6 +349,7 @@ void Module::LoadSymbols() {
const auto aeronid = AeroLib::FindByNid(ids.at(0).c_str()); const auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
const auto nid_name = aeronid ? aeronid->name : "UNK"; const auto nid_name = aeronid ? aeronid->name : "UNK";
LOG_INFO(Core_Linker, "NidName {}", nid_name);
Loader::SymbolResolver sym_r{}; Loader::SymbolResolver sym_r{};
sym_r.name = ids.at(0); sym_r.name = ids.at(0);

View File

@ -119,8 +119,18 @@ public:
return elf.IsSharedLib(); return elf.IsSharedLib();
} }
VAddr GetProcParam() const noexcept { void* FindByName(std::string_view name) {
return proc_param_virtual_addr; const auto symbols = export_sym.GetSymbols();
const auto it = std::ranges::find(symbols, name, &Loader::SymbolRecord::nid_name);
if (it != symbols.end()) {
return reinterpret_cast<void*>(it->virtual_address);
}
return nullptr;
}
template <typename T = VAddr>
const T GetProcParam() const noexcept {
return reinterpret_cast<T>(proc_param_virtual_addr);
} }
std::span<const ModuleInfo> GetImportModules() const { std::span<const ModuleInfo> GetImportModules() const {

View File

@ -247,4 +247,12 @@ void Translator::S_BFE_U32(const GcnInst& inst) {
ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
} }
void Translator::S_LSHL_B32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 result = ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)));
SetDst(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
} // namespace Shader::Gcn } // namespace Shader::Gcn

View File

@ -371,6 +371,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::S_CMP_EQ_U32: case Opcode::S_CMP_EQ_U32:
translator.S_CMP(ConditionOp::EQ, false, inst); translator.S_CMP(ConditionOp::EQ, false, inst);
break; break;
case Opcode::S_LSHL_B32:
translator.S_LSHL_B32(inst);
break;
case Opcode::V_CNDMASK_B32: case Opcode::V_CNDMASK_B32:
translator.V_CNDMASK_B32(inst); translator.V_CNDMASK_B32(inst);
break; break;
@ -527,6 +530,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
case Opcode::S_BFE_U32: case Opcode::S_BFE_U32:
translator.S_BFE_U32(inst); translator.S_BFE_U32(inst);
break; break;
case Opcode::V_RNDNE_F32:
translator.V_RNDNE_F32(inst);
break;
case Opcode::S_NOP: case Opcode::S_NOP:
case Opcode::S_CBRANCH_EXECZ: case Opcode::S_CBRANCH_EXECZ:
case Opcode::S_CBRANCH_SCC0: case Opcode::S_CBRANCH_SCC0:

View File

@ -48,6 +48,7 @@ public:
void S_CSELECT_B32(const GcnInst& inst); void S_CSELECT_B32(const GcnInst& inst);
void S_CSELECT_B64(const GcnInst& inst); void S_CSELECT_B64(const GcnInst& inst);
void S_BFE_U32(const GcnInst& inst); void S_BFE_U32(const GcnInst& inst);
void S_LSHL_B32(const GcnInst& inst);
// Scalar Memory // Scalar Memory
void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); void S_LOAD_DWORD(int num_dwords, const GcnInst& inst);
@ -102,6 +103,7 @@ public:
void V_LSHR_B32(const GcnInst& inst); void V_LSHR_B32(const GcnInst& inst);
void V_ASHRREV_I32(const GcnInst& inst); void V_ASHRREV_I32(const GcnInst& inst);
void V_MAD_U32_U24(const GcnInst& inst); void V_MAD_U32_U24(const GcnInst& inst);
void V_RNDNE_F32(const GcnInst& inst);
// Vector Memory // Vector Memory
void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, const GcnInst& inst); void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, const GcnInst& inst);

View File

@ -367,4 +367,9 @@ void Translator::V_MAD_U32_U24(const GcnInst& inst) {
V_MAD_I32_I24(inst); V_MAD_I32_I24(inst);
} }
void Translator::V_RNDNE_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc(inst.src[0], true)};
SetDst(inst.dst[0], ir.FPRoundEven(src0));
}
} // namespace Shader::Gcn } // namespace Shader::Gcn

View File

@ -31,7 +31,7 @@ void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
void Translator::IMAGE_SAMPLE(const GcnInst& inst) { void Translator::IMAGE_SAMPLE(const GcnInst& inst) {
const auto& mimg = inst.control.mimg; const auto& mimg = inst.control.mimg;
ASSERT(!mimg.da); //ASSERT(!mimg.da);
IR::VectorReg addr_reg{inst.src[0].code}; IR::VectorReg addr_reg{inst.src[0].code};
IR::VectorReg dest_reg{inst.dst[0].code}; IR::VectorReg dest_reg{inst.dst[0].code};

View File

@ -252,6 +252,16 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
} }
break; break;
} }
case PM4ItOpcode::DrawIndexOffset2: {
const auto* draw_index_off = reinterpret_cast<const PM4CmdDrawIndexOffset2*>(header);
regs.max_index_size = draw_index_off->max_size;
regs.num_indices = draw_index_off->index_count;
regs.draw_initiator = draw_index_off->draw_initiator;
if (rasterizer) {
rasterizer->Draw(true, draw_index_off->index_offset);
}
break;
}
case PM4ItOpcode::DrawIndexAuto: { case PM4ItOpcode::DrawIndexAuto: {
const auto* draw_index = reinterpret_cast<const PM4CmdDrawIndexAuto*>(header); const auto* draw_index = reinterpret_cast<const PM4CmdDrawIndexAuto*>(header);
regs.num_indices = draw_index->index_count; regs.num_indices = draw_index->index_count;
@ -272,6 +282,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
} }
break; break;
} }
case PM4ItOpcode::NumInstances: {
const auto* num_instances = reinterpret_cast<const PM4CmdDrawNumInstances*>(header);
regs.num_instances.num_instances = num_instances->num_instances;
break;
}
case PM4ItOpcode::IndexBase: {
const auto* index_base = reinterpret_cast<const PM4CmdDrawIndexBase*>(header);
regs.index_base_address.base_addr_lo = index_base->addr_lo;
regs.index_base_address.base_addr_hi.Assign(index_base->addr_hi);
break;
}
case PM4ItOpcode::EventWrite: { case PM4ItOpcode::EventWrite: {
// const auto* event = reinterpret_cast<const PM4CmdEventWrite*>(header); // const auto* event = reinterpret_cast<const PM4CmdEventWrite*>(header);
break; break;

View File

@ -548,4 +548,15 @@ struct PM4CmdDispatchDirect {
u32 dispatch_initiator; ///< Dispatch Initiator Register u32 dispatch_initiator; ///< Dispatch Initiator Register
}; };
struct PM4CmdDrawNumInstances {
PM4Type3Header header;
u32 num_instances;
};
struct PM4CmdDrawIndexBase {
PM4Type3Header header;
u32 addr_lo;
u32 addr_hi;
};
} // namespace AmdGpu } // namespace AmdGpu

View File

@ -309,6 +309,12 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu
if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Srgb) { if (data_format == AmdGpu::DataFormat::FormatBc3 && num_format == AmdGpu::NumberFormat::Srgb) {
return vk::Format::eBc3SrgbBlock; return vk::Format::eBc3SrgbBlock;
} }
if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && num_format == AmdGpu::NumberFormat::Sint) {
return vk::Format::eR16G16B16A16Sint;
}
if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Srgb) {
return vk::Format::eBc7SrgbBlock;
}
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -81,8 +81,17 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
ComputePipeline::~ComputePipeline() = default; ComputePipeline::~ComputePipeline() = default;
void ComputePipeline::BindResources(Core::MemoryManager* memory, void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
VideoCore::TextureCache& texture_cache) const { VideoCore::TextureCache& texture_cache) const {
static constexpr u64 MinUniformAlignment = 64;
const auto map_staging = [&](auto src, size_t size) {
const auto [data, offset, _] = staging.Map(size, MinUniformAlignment);
std::memcpy(data, reinterpret_cast<const void*>(src), size);
staging.Commit(size);
return offset;
};
// Bind resource buffers and textures. // Bind resource buffers and textures.
boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_infos; boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_infos;
boost::container::static_vector<vk::DescriptorImageInfo, 8> image_infos; boost::container::static_vector<vk::DescriptorImageInfo, 8> image_infos;
@ -94,8 +103,9 @@ void ComputePipeline::BindResources(Core::MemoryManager* memory,
const u32 size = vsharp.GetSize(); const u32 size = vsharp.GetSize();
const VAddr addr = vsharp.base_address.Value(); const VAddr addr = vsharp.base_address.Value();
texture_cache.OnCpuWrite(addr); texture_cache.OnCpuWrite(addr);
const auto [vk_buffer, offset] = memory->GetVulkanBuffer(addr); const u32 offset = map_staging(addr, size);
buffer_infos.emplace_back(vk_buffer, offset, size); //const auto [vk_buffer, offset] = memory->GetVulkanBuffer(addr);
buffer_infos.emplace_back(staging.Handle(), offset, size);
set_writes.push_back({ set_writes.push_back({
.dstSet = VK_NULL_HANDLE, .dstSet = VK_NULL_HANDLE,
.dstBinding = binding++, .dstBinding = binding++,

View File

@ -31,7 +31,8 @@ public:
return *pipeline; return *pipeline;
} }
void BindResources(Core::MemoryManager* memory, VideoCore::TextureCache& texture_cache) const; void BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
VideoCore::TextureCache& texture_cache) const;
private: private:
const Instance& instance; const Instance& instance;

View File

@ -32,16 +32,15 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
Rasterizer::~Rasterizer() = default; Rasterizer::~Rasterizer() = default;
void Rasterizer::Draw(bool is_indexed) { void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
const auto cmdbuf = scheduler.CommandBuffer(); const auto cmdbuf = scheduler.CommandBuffer();
const auto& regs = liverpool->regs; const auto& regs = liverpool->regs;
const u32 num_indices = SetupIndexBuffer(is_indexed); const u32 num_indices = SetupIndexBuffer(is_indexed, index_offset);
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline(); const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
pipeline->BindResources(memory, vertex_index_buffer, texture_cache); pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers> boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers>
color_attachments{}; color_attachments{};
const std::array color = {0.5f, 0.5f, 0.5f, 1.f};
for (auto col_buf_id = 0u; col_buf_id < Liverpool::NumColorBuffers; ++col_buf_id) { for (auto col_buf_id = 0u; col_buf_id < Liverpool::NumColorBuffers; ++col_buf_id) {
const auto& col_buf = regs.color_buffers[col_buf_id]; const auto& col_buf = regs.color_buffers[col_buf_id];
if (!col_buf) { if (!col_buf) {
@ -54,12 +53,10 @@ void Rasterizer::Draw(bool is_indexed) {
color_attachments.push_back({ color_attachments.push_back({
.imageView = *image_view.image_view, .imageView = *image_view.image_view,
.imageLayout = vk::ImageLayout::eGeneral, .imageLayout = vk::ImageLayout::eGeneral,
.loadOp = compute_done ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, .loadOp = vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore, .storeOp = vk::AttachmentStoreOp::eStore,
.clearValue = vk::ClearValue{color},
}); });
} }
compute_done = false;
// TODO: Don't restart renderpass every draw // TODO: Don't restart renderpass every draw
const auto& scissor = regs.screen_scissor; const auto& scissor = regs.screen_scissor;
@ -88,18 +85,16 @@ void Rasterizer::Draw(bool is_indexed) {
} }
void Rasterizer::DispatchDirect() { void Rasterizer::DispatchDirect() {
compute_done = true;
return;
const auto cmdbuf = scheduler.CommandBuffer(); const auto cmdbuf = scheduler.CommandBuffer();
const auto& cs_program = liverpool->regs.cs_program; const auto& cs_program = liverpool->regs.cs_program;
const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline(); const ComputePipeline* pipeline = pipeline_cache.GetComputePipeline();
pipeline->BindResources(memory, texture_cache); pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle()); cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z); cmdbuf.dispatch(cs_program.dim_x, cs_program.dim_y, cs_program.dim_z);
} }
u32 Rasterizer::SetupIndexBuffer(bool& is_indexed) { u32 Rasterizer::SetupIndexBuffer(bool& is_indexed, u32 index_offset) {
// Emulate QuadList primitive type with CPU made index buffer. // Emulate QuadList primitive type with CPU made index buffer.
const auto& regs = liverpool->regs; const auto& regs = liverpool->regs;
if (liverpool->regs.primitive_type == Liverpool::PrimitiveType::QuadList) { if (liverpool->regs.primitive_type == Liverpool::PrimitiveType::QuadList) {
@ -135,7 +130,7 @@ u32 Rasterizer::SetupIndexBuffer(bool& is_indexed) {
// Bind index buffer. // Bind index buffer.
const auto cmdbuf = scheduler.CommandBuffer(); const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.bindIndexBuffer(vertex_index_buffer.Handle(), offset, index_type); cmdbuf.bindIndexBuffer(vertex_index_buffer.Handle(), offset + index_offset * index_size, index_type);
return regs.num_indices; return regs.num_indices;
} }

View File

@ -29,12 +29,12 @@ public:
VideoCore::TextureCache& texture_cache, AmdGpu::Liverpool* liverpool); VideoCore::TextureCache& texture_cache, AmdGpu::Liverpool* liverpool);
~Rasterizer(); ~Rasterizer();
void Draw(bool is_indexed); void Draw(bool is_indexed, u32 index_offset = 0);
void DispatchDirect(); void DispatchDirect();
private: private:
u32 SetupIndexBuffer(bool& is_indexed); u32 SetupIndexBuffer(bool& is_indexed, u32 index_offset);
void MapMemory(VAddr addr, size_t size); void MapMemory(VAddr addr, size_t size);
void UpdateDynamicState(const GraphicsPipeline& pipeline); void UpdateDynamicState(const GraphicsPipeline& pipeline);
@ -49,7 +49,6 @@ private:
Core::MemoryManager* memory; Core::MemoryManager* memory;
PipelineCache pipeline_cache; PipelineCache pipeline_cache;
StreamBuffer vertex_index_buffer; StreamBuffer vertex_index_buffer;
bool compute_done{};
}; };
} // namespace Vulkan } // namespace Vulkan