kernel: Module loading
This commit is contained in:
parent
611745170e
commit
48a158f18a
|
@ -52,7 +52,6 @@ std::string MntPoints::GetHostFile(const std::string& guest_file) {
|
|||
if (find == 0) {
|
||||
std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1);
|
||||
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
|
||||
fmt::print("GetHostFile: {}\n", pair.host_path + npath);
|
||||
return pair.host_path + npath;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI Unknown1() {
|
||||
return 0x81100004;
|
||||
s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char *moduleFileName, size_t args, const void *argp,
|
||||
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) {
|
||||
LIB_FUNCTION("fJgP+wqifno", "libSceDiscMap", 1, "libSceDiscMap", 1, 1, Unknown1);
|
||||
|
||||
// obj
|
||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||
// memory
|
||||
|
@ -260,6 +289,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory);
|
||||
LIB_FUNCTION("rVjRvHJ0X6c", "libkernel", 1, "libkernel", 1, 1, sceKernelVirtualQuery);
|
||||
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
|
||||
LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue);
|
||||
|
|
|
@ -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)) {
|
||||
LOG_ERROR(Core_Linker, "Provided file {} does not exist", elf_name.string());
|
||||
return nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto module = std::make_unique<Module>(elf_name);
|
||||
if (!module->IsValid()) {
|
||||
LOG_ERROR(Core_Linker, "Provided file {} is not valid ELF file", elf_name.string());
|
||||
return nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!module->IsSharedLib()) {
|
||||
main_proc_param_addr = module->GetProcParam();
|
||||
}
|
||||
|
||||
return m_modules.emplace_back(std::move(module)).get();
|
||||
m_modules.emplace_back(std::move(module));
|
||||
return m_modules.size() - 1;
|
||||
}
|
||||
|
||||
void Linker::Relocate(Module* module) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "core/module.h"
|
||||
|
||||
|
@ -29,7 +30,11 @@ public:
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -39,7 +44,7 @@ public:
|
|||
void* TlsGetAddr(u64 module_index, u64 offset);
|
||||
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 Resolve(const std::string& name, Loader::SymbolType type,
|
||||
|
@ -49,15 +54,14 @@ public:
|
|||
|
||||
private:
|
||||
const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l);
|
||||
void InitTls();
|
||||
|
||||
std::mutex mutex;
|
||||
u32 dtv_generation_counter{1};
|
||||
size_t static_tls_size{};
|
||||
size_t max_tls_index{};
|
||||
HeapApiFunc heap_api_func{};
|
||||
std::vector<std::unique_ptr<Module>> m_modules;
|
||||
Loader::SymbolsResolver m_hle_symbols{};
|
||||
VAddr main_proc_param_addr{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace Core::Loader {
|
||||
|
||||
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) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <span>
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
|
@ -20,6 +21,7 @@ enum class SymbolType {
|
|||
|
||||
struct SymbolRecord {
|
||||
std::string name;
|
||||
std::string nid_name;
|
||||
u64 virtual_address;
|
||||
};
|
||||
|
||||
|
@ -42,6 +44,10 @@ public:
|
|||
void AddSymbol(const SymbolResolver& s, u64 virtual_addr);
|
||||
const SymbolRecord* FindSymbol(const SymbolResolver& s) const;
|
||||
|
||||
std::span<const SymbolRecord> GetSymbols() const {
|
||||
return m_symbols;
|
||||
}
|
||||
|
||||
size_t GetSize() const noexcept {
|
||||
return m_symbols.size();
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ MemoryManager::VMAHandle MemoryManager::MergeAdjacent(VMAHandle iter) {
|
|||
}
|
||||
|
||||
void MemoryManager::MapVulkanMemory(VAddr addr, size_t size) {
|
||||
return;
|
||||
//return;
|
||||
const vk::Device device = instance->GetDevice();
|
||||
const auto memory_props = instance->GetPhysicalDevice().getMemoryProperties();
|
||||
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) {
|
||||
return;
|
||||
//return;
|
||||
const auto it = mapped_memories.find(addr);
|
||||
ASSERT(it != mapped_memories.end() && it->second.buffer_size == size);
|
||||
mapped_memories.erase(it);
|
||||
|
|
|
@ -349,6 +349,7 @@ void Module::LoadSymbols() {
|
|||
|
||||
const auto aeronid = AeroLib::FindByNid(ids.at(0).c_str());
|
||||
const auto nid_name = aeronid ? aeronid->name : "UNK";
|
||||
LOG_INFO(Core_Linker, "NidName {}", nid_name);
|
||||
|
||||
Loader::SymbolResolver sym_r{};
|
||||
sym_r.name = ids.at(0);
|
||||
|
|
|
@ -119,8 +119,18 @@ public:
|
|||
return elf.IsSharedLib();
|
||||
}
|
||||
|
||||
VAddr GetProcParam() const noexcept {
|
||||
return proc_param_virtual_addr;
|
||||
void* FindByName(std::string_view name) {
|
||||
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 {
|
||||
|
|
|
@ -247,4 +247,12 @@ void Translator::S_BFE_U32(const GcnInst& inst) {
|
|||
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
|
||||
|
|
|
@ -371,6 +371,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
|
|||
case Opcode::S_CMP_EQ_U32:
|
||||
translator.S_CMP(ConditionOp::EQ, false, inst);
|
||||
break;
|
||||
case Opcode::S_LSHL_B32:
|
||||
translator.S_LSHL_B32(inst);
|
||||
break;
|
||||
case Opcode::V_CNDMASK_B32:
|
||||
translator.V_CNDMASK_B32(inst);
|
||||
break;
|
||||
|
@ -527,6 +530,9 @@ void Translate(IR::Block* block, std::span<const GcnInst> inst_list, Info& info)
|
|||
case Opcode::S_BFE_U32:
|
||||
translator.S_BFE_U32(inst);
|
||||
break;
|
||||
case Opcode::V_RNDNE_F32:
|
||||
translator.V_RNDNE_F32(inst);
|
||||
break;
|
||||
case Opcode::S_NOP:
|
||||
case Opcode::S_CBRANCH_EXECZ:
|
||||
case Opcode::S_CBRANCH_SCC0:
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
void S_CSELECT_B32(const GcnInst& inst);
|
||||
void S_CSELECT_B64(const GcnInst& inst);
|
||||
void S_BFE_U32(const GcnInst& inst);
|
||||
void S_LSHL_B32(const GcnInst& inst);
|
||||
|
||||
// Scalar Memory
|
||||
void S_LOAD_DWORD(int num_dwords, const GcnInst& inst);
|
||||
|
@ -102,6 +103,7 @@ public:
|
|||
void V_LSHR_B32(const GcnInst& inst);
|
||||
void V_ASHRREV_I32(const GcnInst& inst);
|
||||
void V_MAD_U32_U24(const GcnInst& inst);
|
||||
void V_RNDNE_F32(const GcnInst& inst);
|
||||
|
||||
// Vector Memory
|
||||
void BUFFER_LOAD_FORMAT(u32 num_dwords, bool is_typed, const GcnInst& inst);
|
||||
|
|
|
@ -367,4 +367,9 @@ void Translator::V_MAD_U32_U24(const GcnInst& 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
|
||||
|
|
|
@ -31,7 +31,7 @@ void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
|
|||
|
||||
void Translator::IMAGE_SAMPLE(const GcnInst& inst) {
|
||||
const auto& mimg = inst.control.mimg;
|
||||
ASSERT(!mimg.da);
|
||||
//ASSERT(!mimg.da);
|
||||
|
||||
IR::VectorReg addr_reg{inst.src[0].code};
|
||||
IR::VectorReg dest_reg{inst.dst[0].code};
|
||||
|
|
|
@ -252,6 +252,16 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||
}
|
||||
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: {
|
||||
const auto* draw_index = reinterpret_cast<const PM4CmdDrawIndexAuto*>(header);
|
||||
regs.num_indices = draw_index->index_count;
|
||||
|
@ -272,6 +282,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||
}
|
||||
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: {
|
||||
// const auto* event = reinterpret_cast<const PM4CmdEventWrite*>(header);
|
||||
break;
|
||||
|
|
|
@ -548,4 +548,15 @@ struct PM4CmdDispatchDirect {
|
|||
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
|
||||
|
|
|
@ -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) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,17 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
|
|||
|
||||
ComputePipeline::~ComputePipeline() = default;
|
||||
|
||||
void ComputePipeline::BindResources(Core::MemoryManager* memory,
|
||||
void ComputePipeline::BindResources(Core::MemoryManager* memory, StreamBuffer& staging,
|
||||
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.
|
||||
boost::container::static_vector<vk::DescriptorBufferInfo, 4> buffer_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 VAddr addr = vsharp.base_address.Value();
|
||||
texture_cache.OnCpuWrite(addr);
|
||||
const auto [vk_buffer, offset] = memory->GetVulkanBuffer(addr);
|
||||
buffer_infos.emplace_back(vk_buffer, offset, size);
|
||||
const u32 offset = map_staging(addr, size);
|
||||
//const auto [vk_buffer, offset] = memory->GetVulkanBuffer(addr);
|
||||
buffer_infos.emplace_back(staging.Handle(), offset, size);
|
||||
set_writes.push_back({
|
||||
.dstSet = VK_NULL_HANDLE,
|
||||
.dstBinding = binding++,
|
||||
|
|
|
@ -31,7 +31,8 @@ public:
|
|||
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:
|
||||
const Instance& instance;
|
||||
|
|
|
@ -32,16 +32,15 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
|
|||
|
||||
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& 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();
|
||||
pipeline->BindResources(memory, vertex_index_buffer, texture_cache);
|
||||
|
||||
boost::container::static_vector<vk::RenderingAttachmentInfo, Liverpool::NumColorBuffers>
|
||||
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) {
|
||||
const auto& col_buf = regs.color_buffers[col_buf_id];
|
||||
if (!col_buf) {
|
||||
|
@ -54,12 +53,10 @@ void Rasterizer::Draw(bool is_indexed) {
|
|||
color_attachments.push_back({
|
||||
.imageView = *image_view.image_view,
|
||||
.imageLayout = vk::ImageLayout::eGeneral,
|
||||
.loadOp = compute_done ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
|
||||
.loadOp = vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.clearValue = vk::ClearValue{color},
|
||||
});
|
||||
}
|
||||
compute_done = false;
|
||||
|
||||
// TODO: Don't restart renderpass every draw
|
||||
const auto& scissor = regs.screen_scissor;
|
||||
|
@ -88,18 +85,16 @@ void Rasterizer::Draw(bool is_indexed) {
|
|||
}
|
||||
|
||||
void Rasterizer::DispatchDirect() {
|
||||
compute_done = true;
|
||||
return;
|
||||
const auto cmdbuf = scheduler.CommandBuffer();
|
||||
const auto& cs_program = liverpool->regs.cs_program;
|
||||
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.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.
|
||||
const auto& regs = liverpool->regs;
|
||||
if (liverpool->regs.primitive_type == Liverpool::PrimitiveType::QuadList) {
|
||||
|
@ -135,7 +130,7 @@ u32 Rasterizer::SetupIndexBuffer(bool& is_indexed) {
|
|||
|
||||
// Bind index buffer.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@ public:
|
|||
VideoCore::TextureCache& texture_cache, AmdGpu::Liverpool* liverpool);
|
||||
~Rasterizer();
|
||||
|
||||
void Draw(bool is_indexed);
|
||||
void Draw(bool is_indexed, u32 index_offset = 0);
|
||||
|
||||
void DispatchDirect();
|
||||
|
||||
private:
|
||||
u32 SetupIndexBuffer(bool& is_indexed);
|
||||
u32 SetupIndexBuffer(bool& is_indexed, u32 index_offset);
|
||||
void MapMemory(VAddr addr, size_t size);
|
||||
|
||||
void UpdateDynamicState(const GraphicsPipeline& pipeline);
|
||||
|
@ -49,7 +49,6 @@ private:
|
|||
Core::MemoryManager* memory;
|
||||
PipelineCache pipeline_cache;
|
||||
StreamBuffer vertex_index_buffer;
|
||||
bool compute_done{};
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
Loading…
Reference in New Issue