memory: Implement VirtualQuery
This commit is contained in:
parent
1dd815d07d
commit
611745170e
|
@ -18,6 +18,7 @@
|
||||||
#include "core/libraries/kernel/time_management.h"
|
#include "core/libraries/kernel/time_management.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/linker.h"
|
#include "core/linker.h"
|
||||||
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
@ -220,7 +221,28 @@ s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
|
||||||
strlen(std::fgets(static_cast<char*>(buf), static_cast<int>(nbytes), stdin)));
|
strlen(std::fgets(static_cast<char*>(buf), static_cast<int>(nbytes), stdin)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t PS4_SYSV_ABI sceKernelPread(int fd, void *buf, size_t count, uint64_t offset) {
|
||||||
|
long unsigned int read_bytes = 0;
|
||||||
|
|
||||||
|
OVERLAPPED overlapped;
|
||||||
|
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
||||||
|
|
||||||
|
overlapped.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 32);
|
||||||
|
overlapped.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
|
||||||
|
|
||||||
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
|
auto& file = h->GetFile(fd)->f;
|
||||||
|
file.Seek(offset);
|
||||||
|
return file.ReadRaw<u8>(buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI Unknown1() {
|
||||||
|
return 0x81100004;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -232,9 +254,11 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("WFcfL2lzido", "libkernel", 1, "libkernel", 1, 1, sceKernelQueryMemoryProtection);
|
LIB_FUNCTION("WFcfL2lzido", "libkernel", 1, "libkernel", 1, 1, sceKernelQueryMemoryProtection);
|
||||||
LIB_FUNCTION("BHouLQzh0X0", "libkernel", 1, "libkernel", 1, 1, sceKernelDirectMemoryQuery);
|
LIB_FUNCTION("BHouLQzh0X0", "libkernel", 1, "libkernel", 1, 1, sceKernelDirectMemoryQuery);
|
||||||
LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory);
|
LIB_FUNCTION("MBuItvba6z8", "libkernel", 1, "libkernel", 1, 1, sceKernelReleaseDirectMemory);
|
||||||
|
LIB_FUNCTION("hwVSPCmp5tM", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckedReleaseDirectMemory);
|
||||||
LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap);
|
LIB_FUNCTION("cQke9UuBQOk", "libkernel", 1, "libkernel", 1, 1, sceKernelMunmap);
|
||||||
LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory);
|
LIB_FUNCTION("mL8NDH86iQI", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedFlexibleMemory);
|
||||||
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("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI);
|
LIB_FUNCTION("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI);
|
||||||
|
|
||||||
// equeue
|
// equeue
|
||||||
|
@ -254,6 +278,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
||||||
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
||||||
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
|
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
|
||||||
|
LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
|
||||||
|
|
||||||
Libraries::Kernel::fileSystemSymbolsRegister(sym);
|
Libraries::Kernel::fileSystemSymbolsRegister(sym);
|
||||||
Libraries::Kernel::timeSymbolsRegister(sym);
|
Libraries::Kernel::timeSymbolsRegister(sym);
|
||||||
|
|
|
@ -17,6 +17,11 @@ u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
|
||||||
return SCE_KERNEL_MAIN_DMEM_SIZE;
|
return SCE_KERNEL_MAIN_DMEM_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
|
||||||
|
auto* memory = Core::Memory::Instance();
|
||||||
|
return memory->Free(start, len);
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
|
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
|
||||||
u64 alignment, int memoryType, s64* physAddrOut) {
|
u64 alignment, int memoryType, s64* physAddrOut) {
|
||||||
if (searchStart < 0 || searchEnd <= searchStart) {
|
if (searchStart < 0 || searchEnd <= searchStart) {
|
||||||
|
@ -134,6 +139,11 @@ int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInf
|
||||||
return memory->DirectMemoryQuery(offset, flags == 1, query_info);
|
return memory->DirectMemoryQuery(offset, flags == 1, query_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void *addr, int flags, OrbisVirtualQueryInfo *info, size_t infoSize) {
|
||||||
|
auto* memory = Core::Memory::Instance();
|
||||||
|
return memory->VirtualQuery(std::bit_cast<VAddr>(addr), flags, info);
|
||||||
|
}
|
||||||
|
|
||||||
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func) {
|
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func) {
|
||||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||||
linker->SetHeapApiFunc(func);
|
linker->SetHeapApiFunc(func);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB
|
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB
|
||||||
|
@ -36,7 +37,24 @@ struct OrbisQueryInfo {
|
||||||
int memoryType;
|
int memoryType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OrbisVirtualQueryInfo {
|
||||||
|
uintptr_t start;
|
||||||
|
uintptr_t end;
|
||||||
|
size_t offset;
|
||||||
|
s32 protection;
|
||||||
|
s32 memory_type;
|
||||||
|
union {
|
||||||
|
BitField<0, 1, u32> is_flexible;
|
||||||
|
BitField<1, 1, u32> is_direct;
|
||||||
|
BitField<2, 1, u32> is_stack;
|
||||||
|
BitField<3, 1, u32> is_pooled;
|
||||||
|
BitField<4, 1, u32> is_commited;
|
||||||
|
};
|
||||||
|
std::array<char, 32> name;
|
||||||
|
};
|
||||||
|
|
||||||
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
|
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize();
|
||||||
|
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len);
|
||||||
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
|
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
|
||||||
u64 alignment, int memoryType, s64* physAddrOut);
|
u64 alignment, int memoryType, s64* physAddrOut);
|
||||||
s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType,
|
s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment, int memoryType,
|
||||||
|
@ -52,6 +70,8 @@ int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void**
|
||||||
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
|
int PS4_SYSV_ABI sceKernelDirectMemoryQuery(u64 offset, int flags, OrbisQueryInfo* query_info,
|
||||||
size_t infoSize);
|
size_t infoSize);
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void *addr, int flags, OrbisVirtualQueryInfo *info, size_t infoSize);
|
||||||
|
|
||||||
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func);
|
void PS4_SYSV_ABI _sceKernelRtldSetApplicationHeapAPI(void* func);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
|
@ -1273,6 +1273,7 @@ int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(ScePthreadRw* thread) {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(ScePthreadRw* thread) {
|
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(ScePthreadRw* thread) {
|
||||||
int result = scePthreadRwlockUnlock(thread);
|
int result = scePthreadRwlockUnlock(thread);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -1280,6 +1281,7 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(ScePthreadRw* thread) {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
|
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
|
||||||
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);
|
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);
|
||||||
|
|
|
@ -26,7 +26,7 @@ MemoryManager::~MemoryManager() = default;
|
||||||
|
|
||||||
PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
|
PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
|
||||||
int memory_type) {
|
int memory_type) {
|
||||||
PAddr free_addr = 0;
|
PAddr free_addr = search_start;
|
||||||
|
|
||||||
// Iterate through allocated blocked and find the next free position
|
// Iterate through allocated blocked and find the next free position
|
||||||
for (const auto& block : allocations) {
|
for (const auto& block : allocations) {
|
||||||
|
@ -45,7 +45,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
|
||||||
return free_addr;
|
return free_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::Free(PAddr phys_addr, size_t size) {
|
int MemoryManager::Free(PAddr phys_addr, size_t size) {
|
||||||
const auto it = std::ranges::find_if(allocations, [&](const auto& alloc) {
|
const auto it = std::ranges::find_if(allocations, [&](const auto& alloc) {
|
||||||
return alloc.base == phys_addr && alloc.size == size;
|
return alloc.base == phys_addr && alloc.size == size;
|
||||||
});
|
});
|
||||||
|
@ -53,6 +53,7 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) {
|
||||||
|
|
||||||
// Free the ranges.
|
// Free the ranges.
|
||||||
allocations.erase(it);
|
allocations.erase(it);
|
||||||
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||||
|
@ -137,6 +138,27 @@ int MemoryManager::QueryProtection(VAddr addr, void** start, void** end, u32* pr
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MemoryManager::VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info) {
|
||||||
|
auto it = FindVMA(addr);
|
||||||
|
while (it->second.type == VMAType::Free && flags == 1) {
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& vma = it->second;
|
||||||
|
info->start = vma.base;
|
||||||
|
info->end = vma.base + vma.size;
|
||||||
|
info->is_flexible.Assign(vma.type == VMAType::Flexible);
|
||||||
|
info->is_direct.Assign(vma.type == VMAType::Direct);
|
||||||
|
info->is_commited.Assign(vma.type != VMAType::Free);
|
||||||
|
if (vma.type == VMAType::Direct) {
|
||||||
|
const auto it = std::ranges::find(allocations, vma.base, &DirectMemoryArea::base);
|
||||||
|
ASSERT(it != allocations.end());
|
||||||
|
info->memory_type = it->memory_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next,
|
int MemoryManager::DirectMemoryQuery(PAddr addr, bool find_next,
|
||||||
Libraries::Kernel::OrbisQueryInfo* out_info) {
|
Libraries::Kernel::OrbisQueryInfo* out_info) {
|
||||||
const auto it = std::ranges::find_if(allocations, [&](const DirectMemoryArea& alloc) {
|
const auto it = std::ranges::find_if(allocations, [&](const DirectMemoryArea& alloc) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Instance;
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
struct OrbisQueryInfo;
|
struct OrbisQueryInfo;
|
||||||
|
struct OrbisVirtualQueryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
@ -103,7 +104,7 @@ public:
|
||||||
PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
|
PAddr Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment,
|
||||||
int memory_type);
|
int memory_type);
|
||||||
|
|
||||||
void Free(PAddr phys_addr, size_t size);
|
int Free(PAddr phys_addr, size_t size);
|
||||||
|
|
||||||
int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||||
MemoryMapFlags flags, VMAType type, std::string_view name = "",
|
MemoryMapFlags flags, VMAType type, std::string_view name = "",
|
||||||
|
@ -113,6 +114,8 @@ public:
|
||||||
|
|
||||||
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
int QueryProtection(VAddr addr, void** start, void** end, u32* prot);
|
||||||
|
|
||||||
|
int VirtualQuery(VAddr addr, int flags, Libraries::Kernel::OrbisVirtualQueryInfo* info);
|
||||||
|
|
||||||
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
|
int DirectMemoryQuery(PAddr addr, bool find_next, Libraries::Kernel::OrbisQueryInfo* out_info);
|
||||||
|
|
||||||
std::pair<vk::Buffer, size_t> GetVulkanBuffer(VAddr addr);
|
std::pair<vk::Buffer, size_t> GetVulkanBuffer(VAddr addr);
|
||||||
|
|
|
@ -96,7 +96,7 @@ int main(int argc, char* argv[]) {
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
||||||
if (entry.path().filename() == "libc.prx" ||
|
if (entry.path().filename() == "libc.prx" ||
|
||||||
entry.path().filename() == "libSceFios2.prx" ||
|
entry.path().filename() == "libSceFios2.prx" ||
|
||||||
entry.path().filename() == "libSceNpToolkit2.prx") {
|
entry.path().filename() == "libSceNpToolkit.prx") {
|
||||||
found = true;
|
found = true;
|
||||||
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||||
linker->LoadModule(entry.path().string().c_str());
|
linker->LoadModule(entry.path().string().c_str());
|
||||||
|
|
|
@ -95,9 +95,14 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
case IR::Attribute::FragCoord:
|
case IR::Attribute::FragCoord: {
|
||||||
return ctx.OpLoad(ctx.F32[1],
|
const Id coord = ctx.OpLoad(ctx.F32[1],
|
||||||
ctx.OpAccessChain(ctx.input_f32, ctx.frag_coord, ctx.ConstU32(comp)));
|
ctx.OpAccessChain(ctx.input_f32, ctx.frag_coord, ctx.ConstU32(comp)));
|
||||||
|
if (comp == 3) {
|
||||||
|
return ctx.OpFDiv(ctx.F32[1], ctx.ConstF32(1.f), coord);
|
||||||
|
}
|
||||||
|
return coord;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("Read attribute {}", attr);
|
throw NotImplementedException("Read attribute {}", attr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
||||||
.stride = buffer.GetStride(),
|
.stride = buffer.GetStride(),
|
||||||
.num_records = u32(buffer.num_records),
|
.num_records = u32(buffer.num_records),
|
||||||
.used_types = BufferDataType(inst),
|
.used_types = BufferDataType(inst),
|
||||||
.is_storage = true || IsBufferStore(inst),
|
.is_storage = IsBufferStore(inst),
|
||||||
});
|
});
|
||||||
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
|
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
|
||||||
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
|
@ -205,8 +205,8 @@ void PatchBufferInstruction(IR::Block& block, IR::Inst& inst, Info& info,
|
||||||
const u32 dword_offset = inst_info.inst_offset.Value() / sizeof(u32);
|
const u32 dword_offset = inst_info.inst_offset.Value() / sizeof(u32);
|
||||||
IR::U32 address = ir.Imm32(dword_offset);
|
IR::U32 address = ir.Imm32(dword_offset);
|
||||||
if (inst_info.index_enable && inst_info.offset_enable) {
|
if (inst_info.index_enable && inst_info.offset_enable) {
|
||||||
const IR::U32 offset{ir.CompositeExtract(inst.Arg(1), 0)};
|
const IR::U32 offset{ir.CompositeExtract(inst.Arg(1), 1)};
|
||||||
const IR::U32 index{ir.CompositeExtract(inst.Arg(1), 1)};
|
const IR::U32 index{ir.CompositeExtract(inst.Arg(1), 0)};
|
||||||
address = ir.IAdd(ir.IMul(index, ir.Imm32(dword_stride)), address);
|
address = ir.IAdd(ir.IMul(index, ir.Imm32(dword_stride)), address);
|
||||||
address = ir.IAdd(address, ir.ShiftRightLogical(offset, ir.Imm32(2)));
|
address = ir.IAdd(address, ir.ShiftRightLogical(offset, ir.Imm32(2)));
|
||||||
} else if (inst_info.index_enable) {
|
} else if (inst_info.index_enable) {
|
||||||
|
|
|
@ -14,6 +14,8 @@ vk::StencilOp StencilOp(Liverpool::StencilFunc op) {
|
||||||
return vk::StencilOp::eKeep;
|
return vk::StencilOp::eKeep;
|
||||||
case Liverpool::StencilFunc::Zero:
|
case Liverpool::StencilFunc::Zero:
|
||||||
return vk::StencilOp::eZero;
|
return vk::StencilOp::eZero;
|
||||||
|
case Liverpool::StencilFunc::ReplaceTest:
|
||||||
|
return vk::StencilOp::eReplace;
|
||||||
case Liverpool::StencilFunc::AddClamp:
|
case Liverpool::StencilFunc::AddClamp:
|
||||||
return vk::StencilOp::eIncrementAndClamp;
|
return vk::StencilOp::eIncrementAndClamp;
|
||||||
case Liverpool::StencilFunc::SubClamp:
|
case Liverpool::StencilFunc::SubClamp:
|
||||||
|
|
Loading…
Reference in New Issue