ParallelRDP integration
This commit is contained in:
20
external/shader.frag
vendored
Normal file
20
external/shader.frag
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#version 450
|
||||
layout(location = 0) in vec2 vUV;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 0) uniform sampler2D uImage;
|
||||
|
||||
layout(push_constant) uniform Screen {
|
||||
vec2 size;
|
||||
vec2 offset;
|
||||
} uScreen;
|
||||
|
||||
layout(constant_id = 0) const float Scale = 1.0;
|
||||
|
||||
void main() {
|
||||
vec2 uv = (vUV - uScreen.offset) / uScreen.size;
|
||||
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
|
||||
FragColor = vec4(0, 0, 0, 1);
|
||||
} else {
|
||||
FragColor = Scale * textureLod(uImage, uv, 0.0);
|
||||
}
|
||||
}
|
||||
8
external/shader.vert
vendored
Normal file
8
external/shader.vert
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
#version 450
|
||||
layout(location = 0) in vec2 Position;
|
||||
layout(location = 0) out highp vec2 vUV;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(Position, 0.0, 1.0);
|
||||
vUV = 0.5 * Position + 0.5;
|
||||
}
|
||||
@@ -24,3 +24,6 @@ using m128 = __m128i;
|
||||
#define KiB * 1024
|
||||
#define MiB (KiB * 1024)
|
||||
#define GiB (MiB * 1024)
|
||||
|
||||
#define N64_CPU_FREQ 93750000
|
||||
#define N64_CYCLES_PER_FRAME (N64_CPU_FREQ / 60)
|
||||
@@ -20,12 +20,19 @@ find_package(fmt REQUIRED)
|
||||
|
||||
add_subdirectory(core)
|
||||
|
||||
set(PARALLELRDP_INCLUDES
|
||||
../../../external/parallel-rdp-standalone/vulkan
|
||||
../../../external/parallel-rdp-standalone/util
|
||||
../../../external/parallel-rdp-standalone/parallel-rdp
|
||||
../../../external/parallel-rdp-standalone/volk
|
||||
../../../external/parallel-rdp-standalone/vulkan-headers)
|
||||
|
||||
add_library(n64
|
||||
Core.hpp
|
||||
Core.cpp
|
||||
memory_regions.hpp
|
||||
../BaseCore.cpp
|
||||
../BaseCore.hpp)
|
||||
target_include_directories(n64 PRIVATE . ..)
|
||||
target_include_directories(n64 PRIVATE . .. ../../frontend/sdl ${PARALLELRDP_INCLUDES})
|
||||
target_include_directories(n64 PUBLIC ${mio_SOURCE_DIR}/include ${toml11_SOURCE_DIR}/include)
|
||||
target_link_libraries(n64 PRIVATE mio::mio toml11::toml11 fmt::fmt n64-core)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <Core.hpp>
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <ParallelRDPWrapper.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
Core::Core(const std::string& rom) {
|
||||
mem.LoadROM(rom);
|
||||
LoadParallelRDP(mem.GetRDRAM());
|
||||
}
|
||||
|
||||
void Core::Run() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include <BaseCore.hpp>
|
||||
#include "n64/core/Cpu.hpp"
|
||||
#include "n64/core/Mem.hpp"
|
||||
#include <n64/core/Cpu.hpp>
|
||||
#include <n64/core/Mem.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
|
||||
@@ -7,7 +7,11 @@ add_library(n64-core
|
||||
Cpu.hpp
|
||||
Cpu.cpp
|
||||
Mem.cpp
|
||||
Mem.hpp RDP.cpp RDP.hpp)
|
||||
Mem.hpp
|
||||
RDP.cpp
|
||||
RDP.hpp
|
||||
mmio/VI.cpp
|
||||
mmio/VI.hpp mmio/Interrupt.hpp mmio/MI.cpp mmio/MI.hpp mmio/Interrupt.cpp)
|
||||
|
||||
target_include_directories(n64-core PRIVATE . .. ../../)
|
||||
target_include_directories(n64-core PRIVATE . .. ../../ mmio)
|
||||
target_link_libraries(n64-core PUBLIC n64-cpu)
|
||||
|
||||
@@ -1 +1 @@
|
||||
#include "Cpu.hpp"
|
||||
#include <Cpu.hpp>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "n64/core/cpu/Registers.hpp"
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
struct Cpu {
|
||||
|
||||
@@ -8,6 +8,9 @@ struct Mem {
|
||||
~Mem() = default;
|
||||
Mem();
|
||||
void LoadROM(const std::string&);
|
||||
[[nodiscard]] auto GetRDRAM() const -> const u8* {
|
||||
return rdram.data();
|
||||
}
|
||||
private:
|
||||
std::vector<u8> cart, rdram, sram;
|
||||
u8 dmem[DMEM_SIZE]{}, imem[IMEM_SIZE]{}, pifRam[PIF_RAM_SIZE]{};
|
||||
|
||||
58
src/core/n64/core/mmio/Interrupt.cpp
Normal file
58
src/core/n64/core/mmio/Interrupt.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <Interrupt.hpp>
|
||||
#include <MI.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
void InterruptRaise(MI &mi, Registers ®s, InterruptType intr) {
|
||||
switch(intr) {
|
||||
case InterruptType::VI:
|
||||
mi.miIntr.vi = true;
|
||||
break;
|
||||
case InterruptType::SI:
|
||||
mi.miIntr.si = true;
|
||||
break;
|
||||
case InterruptType::PI:
|
||||
mi.miIntr.pi = true;
|
||||
break;
|
||||
case InterruptType::AI:
|
||||
mi.miIntr.ai = true;
|
||||
break;
|
||||
case InterruptType::DP:
|
||||
mi.miIntr.dp = true;
|
||||
break;
|
||||
case InterruptType::SP:
|
||||
mi.miIntr.sp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateInterrupt(mi, regs);
|
||||
}
|
||||
void InterruptLower(MI &mi, Registers ®s, InterruptType intr) {
|
||||
switch(intr) {
|
||||
case InterruptType::VI:
|
||||
mi.miIntr.vi = false;
|
||||
break;
|
||||
case InterruptType::SI:
|
||||
mi.miIntr.si = false;
|
||||
break;
|
||||
case InterruptType::PI:
|
||||
mi.miIntr.pi = false;
|
||||
break;
|
||||
case InterruptType::AI:
|
||||
mi.miIntr.ai = false;
|
||||
break;
|
||||
case InterruptType::DP:
|
||||
mi.miIntr.dp = false;
|
||||
break;
|
||||
case InterruptType::SP:
|
||||
mi.miIntr.sp = false;
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateInterrupt(mi, regs);
|
||||
}
|
||||
void UpdateInterrupt(MI &mi, Registers ®s) {
|
||||
bool interrupt = mi.miIntr.raw & mi.miIntrMask.raw;
|
||||
regs.cop0.cause.ip2 = interrupt;
|
||||
}
|
||||
}
|
||||
16
src/core/n64/core/mmio/Interrupt.hpp
Normal file
16
src/core/n64/core/mmio/Interrupt.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
#include <MI.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
|
||||
struct Registers;
|
||||
|
||||
enum class InterruptType : u8 {
|
||||
VI, SI, PI, AI, DP, SP
|
||||
};
|
||||
|
||||
void InterruptRaise(MI &mi, Registers ®s, InterruptType intr);
|
||||
void InterruptLower(MI &mi, Registers ®s, InterruptType intr);
|
||||
void UpdateInterrupt(MI &mi, Registers ®s);
|
||||
}
|
||||
79
src/core/n64/core/mmio/MI.cpp
Normal file
79
src/core/n64/core/mmio/MI.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <MI.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
#include <util.hpp>
|
||||
#include <Interrupt.hpp>
|
||||
|
||||
#define MI_VERSION_REG 0x02020102
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
MI::MI() {
|
||||
miIntrMask.raw = 0;
|
||||
miIntr.raw = 0;
|
||||
miMode = 0;
|
||||
}
|
||||
|
||||
u32 MI::Read(u32 paddr) {
|
||||
switch(paddr & 0xF) {
|
||||
case 0x0: return miMode & 0x3FF;
|
||||
case 0x4: return MI_VERSION_REG;
|
||||
case 0x8: return miIntr.raw & 0x3F;
|
||||
case 0xC: return miIntrMask.raw & 0x3F;
|
||||
default: util::panic("Unhandled MI[%08X] read\n", paddr);
|
||||
}
|
||||
}
|
||||
|
||||
void MI::Write(Registers& regs, u32 paddr, u32 val) {
|
||||
switch(paddr & 0xF) {
|
||||
case 0x0:
|
||||
miMode &= 0xFFFFFF80;
|
||||
miMode |= val & 0x7F;
|
||||
if (val & (1 << 7)) {
|
||||
miMode &= ~(1 << 7);
|
||||
}
|
||||
|
||||
if (val & (1 << 8)) {
|
||||
miMode |= 1 << 7;
|
||||
}
|
||||
|
||||
if (val & (1 << 9)) {
|
||||
miMode &= ~(1 << 8);
|
||||
}
|
||||
|
||||
if (val & (1 << 10)) {
|
||||
miMode |= 1 << 8;
|
||||
}
|
||||
|
||||
if (val & (1 << 11)) {
|
||||
InterruptLower(*this, regs, InterruptType::DP);
|
||||
}
|
||||
|
||||
if (val & (1 << 12)) {
|
||||
miMode &= ~(1 << 9);
|
||||
}
|
||||
|
||||
if (val & (1 << 13)) {
|
||||
miMode |= 1 << 9;
|
||||
}
|
||||
break;
|
||||
case 0x4: break;
|
||||
case 0xC:
|
||||
for (int bit = 0; bit < 6; bit++) {
|
||||
int clearbit = bit << 1;
|
||||
int setbit = (bit << 1) + 1;
|
||||
|
||||
if (val & (1 << clearbit)) {
|
||||
miIntrMask.raw &= ~(1 << bit);
|
||||
}
|
||||
|
||||
if (val & (1 << setbit)) {
|
||||
miIntrMask.raw |= 1 << bit;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateInterrupt(*this, regs);
|
||||
break;
|
||||
default:
|
||||
util::panic("Unhandled MI[%08X] write (%08X)\n", val, paddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/core/n64/core/mmio/MI.hpp
Normal file
29
src/core/n64/core/mmio/MI.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
|
||||
union MIIntr {
|
||||
struct {
|
||||
unsigned sp: 1;
|
||||
unsigned si: 1;
|
||||
unsigned ai: 1;
|
||||
unsigned vi: 1;
|
||||
unsigned pi: 1;
|
||||
unsigned dp: 1;
|
||||
unsigned: 26;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
struct Registers;
|
||||
|
||||
struct MI {
|
||||
MI();
|
||||
u32 Read(u32);
|
||||
void Write(Registers& regs, u32, u32);
|
||||
|
||||
u32 miMode;
|
||||
MIIntr miIntr{}, miIntrMask{};
|
||||
};
|
||||
}
|
||||
83
src/core/n64/core/mmio/VI.cpp
Normal file
83
src/core/n64/core/mmio/VI.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <VI.hpp>
|
||||
#include <util.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
#include <MI.hpp>
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
VI::VI () {
|
||||
status.raw = 0xF;
|
||||
intr = 256;
|
||||
origin = 0;
|
||||
width = 320;
|
||||
current = 0;
|
||||
vsync = 0;
|
||||
hsync = 0;
|
||||
numHalflines = 262;
|
||||
numFields = 1;
|
||||
cyclesPerHalfline = 1000;
|
||||
}
|
||||
|
||||
u32 VI::Read(u32 paddr) {
|
||||
switch(paddr) {
|
||||
case 0x04400000: return status.raw;
|
||||
case 0x04400004: return origin;
|
||||
case 0x04400008: return width;
|
||||
case 0x0440000C: return intr;
|
||||
case 0x04400010: return current << 1;
|
||||
case 0x04400014: return burst.raw;
|
||||
case 0x04400018: return vsync;
|
||||
case 0x0440001C: return hsync;
|
||||
case 0x04400020: return hsyncLeap.raw;
|
||||
case 0x04400024: return hvideo.raw;
|
||||
case 0x04400028: return vvideo.raw;
|
||||
case 0x0440002C: return vburst.raw;
|
||||
case 0x04400030: return xscale.raw;
|
||||
case 0x04400034: return yscale.raw;
|
||||
default:
|
||||
util::panic("Unimplemented VI[%08X] read\n", paddr);
|
||||
}
|
||||
}
|
||||
|
||||
void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
|
||||
switch(paddr) {
|
||||
case 0x04400000:
|
||||
status.raw = val;
|
||||
numFields = status.serrate ? 2 : 1;
|
||||
break;
|
||||
case 0x04400004: {
|
||||
u32 masked = val & 0xFFFFFF;
|
||||
if(origin != masked) {
|
||||
swaps++;
|
||||
}
|
||||
origin = masked;
|
||||
} break;
|
||||
case 0x04400008: {
|
||||
width = val & 0x7FF;
|
||||
} break;
|
||||
case 0x0440000C: {
|
||||
intr = val & 0x3FF;
|
||||
} break;
|
||||
case 0x04400010:
|
||||
InterruptLower(mi, regs, InterruptType::VI);
|
||||
break;
|
||||
case 0x04400014: burst.raw = val; break;
|
||||
case 0x04400018: {
|
||||
vsync = val & 0x3FF;
|
||||
numHalflines = vsync >> 1;
|
||||
cyclesPerHalfline = N64_CYCLES_PER_FRAME / numHalflines;
|
||||
} break;
|
||||
case 0x0440001C: {
|
||||
hsync = val & 0x3FF;
|
||||
} break;
|
||||
case 0x04400020: hsyncLeap.raw = val; break;
|
||||
case 0x04400024: hvideo.raw = val; break;
|
||||
case 0x04400028: vvideo.raw = val; break;
|
||||
case 0x0440002C: vburst.raw = val; break;
|
||||
case 0x04400030: xscale.raw = val; break;
|
||||
case 0x04400034: yscale.raw = val; break;
|
||||
default:
|
||||
util::panic("Unimplemented VI[%08X] write (%08X)\n", paddr, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/core/n64/core/mmio/VI.hpp
Normal file
83
src/core/n64/core/mmio/VI.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
|
||||
namespace natsukashii::n64::core {
|
||||
union VIBurst {
|
||||
struct {
|
||||
unsigned hsyncW:8;
|
||||
unsigned burstW:8;
|
||||
unsigned vsyncW:4;
|
||||
unsigned burstStart:10;
|
||||
unsigned:2;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
union VIHsyncLeap {
|
||||
struct {
|
||||
unsigned leapB:10;
|
||||
unsigned:6;
|
||||
unsigned leapA:10;
|
||||
unsigned:6;
|
||||
};
|
||||
u32 raw;
|
||||
} ;
|
||||
|
||||
union VIVideo {
|
||||
struct {
|
||||
unsigned end:10;
|
||||
unsigned:6;
|
||||
unsigned start:10;
|
||||
unsigned:6;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
union VIScale {
|
||||
struct {
|
||||
unsigned scale:12;
|
||||
unsigned:4;
|
||||
unsigned offset:12;
|
||||
unsigned:4;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
enum VIFormat {
|
||||
blank = 0,
|
||||
reserved = 1,
|
||||
f5553 = 2,
|
||||
f8888 = 3
|
||||
};
|
||||
|
||||
union VIStatus {
|
||||
struct {
|
||||
u8 format:2;
|
||||
unsigned serrate:1;
|
||||
unsigned:29;
|
||||
};
|
||||
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
struct MI;
|
||||
struct Registers;
|
||||
|
||||
struct VI {
|
||||
VI();
|
||||
u32 Read(u32);
|
||||
void Write(MI&, Registers&, u32, u32);
|
||||
VIScale xscale{}, yscale{};
|
||||
VIVideo hvideo{}, vvideo{};
|
||||
VIHsyncLeap hsyncLeap{};
|
||||
VIStatus status{};
|
||||
VIBurst burst{}, vburst{};
|
||||
u32 origin, width, current;
|
||||
u32 vsync, hsync, intr;
|
||||
u32 hstart{}, vstart{};
|
||||
int swaps{};
|
||||
int numHalflines;
|
||||
int numFields;
|
||||
int cyclesPerHalfline;
|
||||
};
|
||||
} // natsukashii::n64::core
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
#include <portable_endian_bswap.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace natsukashii::util {
|
||||
enum MessageType : u8 {
|
||||
@@ -133,4 +134,21 @@ inline size_t NextPow2(size_t num) {
|
||||
num |= num >> 16;
|
||||
return num + 1;
|
||||
}
|
||||
|
||||
inline void ReadFileBinary(const std::string& path, void* buf) {
|
||||
std::ifstream file("external/vert.spv", std::ios::binary);
|
||||
file.unsetf(std::ios::skipws);
|
||||
if(!file.is_open()) {
|
||||
util::panic("Could not load file!\n");
|
||||
}
|
||||
file.seekg(std::ios::end);
|
||||
auto size = file.tellg();
|
||||
file.seekg(std::ios::beg);
|
||||
if(buf)
|
||||
free(buf);
|
||||
|
||||
buf = calloc(size, 1);
|
||||
file.read((char*)buf, size);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <gb/Core.hpp>
|
||||
#include <n64/Core.hpp>
|
||||
#include <volk.h>
|
||||
#include <ParallelRDPWrapper.hpp>
|
||||
|
||||
namespace natsukashii::frontend {
|
||||
using namespace natsukashii;
|
||||
|
||||
@@ -15,7 +15,6 @@ struct App {
|
||||
App(const std::string&, const std::string&);
|
||||
void Run();
|
||||
private:
|
||||
SDL_Window *window = nullptr;
|
||||
SDL_Renderer *renderer = nullptr;
|
||||
u32 id;
|
||||
std::unique_ptr<BaseCore> core;
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
#include <util.hpp>
|
||||
|
||||
using namespace Vulkan;
|
||||
using namespace natsukashii;
|
||||
using namespace natsukashii::n64;
|
||||
using namespace Vulkan;
|
||||
using namespace RDP;
|
||||
using std::unique_ptr;
|
||||
using RDP::CommandProcessor;
|
||||
using RDP::CommandProcessorFlags;
|
||||
using RDP::VIRegister;
|
||||
|
||||
static CommandProcessor* command_processor;
|
||||
static WSI* wsi;
|
||||
@@ -19,7 +18,7 @@ static WSI* wsi;
|
||||
std::vector<Semaphore> acquire_semaphore;
|
||||
|
||||
VkQueue GetGraphicsQueue() {
|
||||
return wsi->get_context().get_graphics_queue();
|
||||
return wsi->get_context().get_queue_info().queues[QUEUE_INDEX_GRAPHICS];
|
||||
}
|
||||
|
||||
VkInstance GetVkInstance() {
|
||||
@@ -35,7 +34,7 @@ VkDevice GetVkDevice() {
|
||||
}
|
||||
|
||||
uint32_t GetVkGraphicsQueueFamily() {
|
||||
return wsi->get_context().get_graphics_queue_family();
|
||||
return wsi->get_context().get_queue_info().family_indices[QUEUE_INDEX_GRAPHICS];
|
||||
}
|
||||
|
||||
VkFormat GetVkFormat() {
|
||||
@@ -94,11 +93,11 @@ public:
|
||||
}
|
||||
|
||||
uint32_t get_surface_width() override {
|
||||
return N64_SCREEN_X * SCREEN_SCALE;
|
||||
return 800;
|
||||
}
|
||||
|
||||
uint32_t get_surface_height() override {
|
||||
return N64_SCREEN_Y * SCREEN_SCALE;
|
||||
return 600;
|
||||
}
|
||||
|
||||
bool alive(Vulkan::WSI &wsi) override {
|
||||
@@ -106,11 +105,14 @@ public:
|
||||
}
|
||||
|
||||
void poll_input() override {
|
||||
n64_poll_input();
|
||||
SDL_Event e;
|
||||
while(SDL_PollEvent(&e)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void event_frame_tick(double frame, double elapsed) override {
|
||||
n64_render_screen();
|
||||
//n64_render_screen();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -125,22 +127,26 @@ void LoadParallelRDP(const u8* rdram) {
|
||||
util::panic("Failed to initialize WSI!");
|
||||
}
|
||||
|
||||
ResourceLayout vert_layout;
|
||||
ResourceLayout frag_layout;
|
||||
ResourceLayout vertLayout;
|
||||
ResourceLayout fragLayout;
|
||||
|
||||
vert_layout.input_mask = 1;
|
||||
vert_layout.output_mask = 1;
|
||||
vertLayout.input_mask = 1;
|
||||
vertLayout.output_mask = 1;
|
||||
|
||||
frag_layout.input_mask = 1;
|
||||
frag_layout.output_mask = 1;
|
||||
frag_layout.spec_constant_mask = 1;
|
||||
frag_layout.push_constant_size = 4 * sizeof(float);
|
||||
fragLayout.input_mask = 1;
|
||||
fragLayout.output_mask = 1;
|
||||
fragLayout.spec_constant_mask = 1;
|
||||
fragLayout.push_constant_size = 4 * sizeof(float);
|
||||
|
||||
frag_layout.sets[0].sampled_image_mask = 1;
|
||||
frag_layout.sets[0].fp_mask = 1;
|
||||
frag_layout.sets[0].array_size[0] = 1;
|
||||
fragLayout.sets[0].sampled_image_mask = 1;
|
||||
fragLayout.sets[0].fp_mask = 1;
|
||||
fragLayout.sets[0].array_size[0] = 1;
|
||||
|
||||
fullscreen_quad_program = wsi->get_device().request_program(fullscreen_quad_vert, sizeof(fullscreen_quad_vert), fullscreen_quad_frag, sizeof(fullscreen_quad_frag), &vert_layout, &frag_layout);
|
||||
u32* fullscreenQuadVert, *fullscreenQuadFrag;
|
||||
util::ReadFileBinary("external/vert.spv", fullscreenQuadVert);
|
||||
util::ReadFileBinary("external/frag.spv", fullscreenQuadFrag);
|
||||
|
||||
fullscreen_quad_program = wsi->get_device().request_program(fullscreenQuadVert, sizeof(fullscreenQuadVert), fullscreenQuadFrag, sizeof(fullscreenQuadFrag), &vertLayout, &fragLayout);
|
||||
|
||||
auto aligned_rdram = reinterpret_cast<uintptr_t>(rdram);
|
||||
uintptr_t offset = 0;
|
||||
@@ -162,7 +168,7 @@ void LoadParallelRDP(const u8* rdram) {
|
||||
}
|
||||
}
|
||||
|
||||
void draw_fullscreen_textured_quad(Util::IntrusivePtr<Image> image, Util::IntrusivePtr<CommandBuffer> cmd) {
|
||||
void DrawFullscreenTexturedQuad(Util::IntrusivePtr<Image> image, Util::IntrusivePtr<CommandBuffer> cmd) {
|
||||
cmd->set_texture(0, 0, image->get_view(), Vulkan::StockSampler::LinearClamp);
|
||||
cmd->set_program(fullscreen_quad_program);
|
||||
cmd->set_quad_state();
|
||||
@@ -200,11 +206,11 @@ void draw_fullscreen_textured_quad(Util::IntrusivePtr<Image> image, Util::Intrus
|
||||
cmd->draw(3, 1);
|
||||
}
|
||||
|
||||
void update_screen(Util::IntrusivePtr<Image> image) {
|
||||
void UpdateScreen(Util::IntrusivePtr<Image> image) {
|
||||
wsi->begin_frame();
|
||||
|
||||
if (!image) {
|
||||
auto info = Vulkan::ImageCreateInfo::immutable_2d_image(N64_SCREEN_X * SCREEN_SCALE, N64_SCREEN_Y * SCREEN_SCALE, VK_FORMAT_R8G8B8A8_UNORM);
|
||||
auto info = Vulkan::ImageCreateInfo::immutable_2d_image(800, 600, VK_FORMAT_R8G8B8A8_UNORM);
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.misc = IMAGE_MISC_MUTABLE_SRGB_BIT;
|
||||
@@ -228,32 +234,28 @@ void update_screen(Util::IntrusivePtr<Image> image) {
|
||||
Util::IntrusivePtr<CommandBuffer> cmd = wsi->get_device().request_command_buffer();
|
||||
|
||||
cmd->begin_render_pass(wsi->get_device().get_swapchain_render_pass(SwapchainRenderPass::ColorOnly));
|
||||
draw_fullscreen_textured_quad(image, cmd);
|
||||
ImGui_ImplVulkan_RenderDrawData(imgui_frame(), cmd->get_command_buffer());
|
||||
DrawFullscreenTexturedQuad(image, cmd);
|
||||
//ImGui_ImplVulkan_RenderDrawData(imgui_frame(), cmd->get_command_buffer());
|
||||
cmd->end_render_pass();
|
||||
wsi->get_device().submit(cmd);
|
||||
wsi->end_frame();
|
||||
}
|
||||
|
||||
void update_screen_parallel_rdp() {
|
||||
if (unlikely(!command_processor)) {
|
||||
logfatal("Update screen without an initialized command processor");
|
||||
}
|
||||
|
||||
command_processor->set_vi_register(VIRegister::Control, n64sys.vi.status.raw);
|
||||
command_processor->set_vi_register(VIRegister::Origin, n64sys.vi.vi_origin);
|
||||
command_processor->set_vi_register(VIRegister::Width, n64sys.vi.vi_width);
|
||||
command_processor->set_vi_register(VIRegister::Intr, n64sys.vi.vi_v_intr);
|
||||
command_processor->set_vi_register(VIRegister::VCurrentLine, n64sys.vi.v_current);
|
||||
command_processor->set_vi_register(VIRegister::Timing, n64sys.vi.vi_burst.raw);
|
||||
command_processor->set_vi_register(VIRegister::VSync, n64sys.vi.vsync);
|
||||
command_processor->set_vi_register(VIRegister::HSync, n64sys.vi.hsync);
|
||||
command_processor->set_vi_register(VIRegister::Leap, n64sys.vi.leap);
|
||||
command_processor->set_vi_register(VIRegister::HStart, n64sys.vi.hstart.raw);
|
||||
command_processor->set_vi_register(VIRegister::VStart, n64sys.vi.vstart.raw);
|
||||
command_processor->set_vi_register(VIRegister::VBurst, n64sys.vi.vburst);
|
||||
command_processor->set_vi_register(VIRegister::XScale, n64sys.vi.xscale.raw);
|
||||
command_processor->set_vi_register(VIRegister::YScale, n64sys.vi.yscale.raw);
|
||||
void UpdateScreenParallelRdp(const n64::core::VI& vi) {
|
||||
command_processor->set_vi_register(VIRegister::Control, vi.status.raw);
|
||||
command_processor->set_vi_register(VIRegister::Origin, vi.origin);
|
||||
command_processor->set_vi_register(VIRegister::Width, vi.width);
|
||||
command_processor->set_vi_register(VIRegister::Intr, vi.intr);
|
||||
command_processor->set_vi_register(VIRegister::VCurrentLine, vi.current);
|
||||
command_processor->set_vi_register(VIRegister::Timing, vi.burst.raw);
|
||||
command_processor->set_vi_register(VIRegister::VSync, vi.vsync);
|
||||
command_processor->set_vi_register(VIRegister::HSync, vi.hsync);
|
||||
command_processor->set_vi_register(VIRegister::Leap, vi.hsyncLeap.raw);
|
||||
command_processor->set_vi_register(VIRegister::HStart, vi.hstart);
|
||||
command_processor->set_vi_register(VIRegister::VStart, vi.vstart);
|
||||
command_processor->set_vi_register(VIRegister::VBurst, vi.burst.raw);
|
||||
command_processor->set_vi_register(VIRegister::XScale, vi.xscale.raw);
|
||||
command_processor->set_vi_register(VIRegister::YScale, vi.yscale.raw);
|
||||
|
||||
RDP::ScanoutOptions opts;
|
||||
opts.persist_frame_on_invalid_input = true;
|
||||
@@ -265,18 +267,18 @@ void update_screen_parallel_rdp() {
|
||||
opts.downscale_steps = true;
|
||||
opts.crop_overscan_pixels = true;
|
||||
Util::IntrusivePtr<Image> image = command_processor->scanout(opts);
|
||||
update_screen(image);
|
||||
UpdateScreen(image);
|
||||
command_processor->begin_frame_context();
|
||||
}
|
||||
|
||||
void update_screen_parallel_rdp_no_game() {
|
||||
update_screen(static_cast<Util::IntrusivePtr<Image>>(nullptr));
|
||||
void UpdateScreenParallelRdpNoGame() {
|
||||
UpdateScreen(static_cast<Util::IntrusivePtr<Image>>(nullptr));
|
||||
}
|
||||
|
||||
void parallel_rdp_enqueue_command(int command_length, word* buffer) {
|
||||
void ParallelRdpEnqueueCommand(int command_length, u32* buffer) {
|
||||
command_processor->enqueue_command(command_length, buffer);
|
||||
}
|
||||
|
||||
void parallel_rdp_on_full_sync() {
|
||||
void ParallelRdpOnFullSync() {
|
||||
command_processor->wait_for_timeline(command_processor->signal_timeline());
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
#pragma once
|
||||
#include <n64/Core.hpp>
|
||||
#include <wsi.hpp>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <n64/core/mmio/VI.hpp>
|
||||
|
||||
static SDL_Window* window;
|
||||
VkQueue GetGraphicsQueue();
|
||||
VkInstance GetVkInstance();
|
||||
VkPhysicalDevice GetVkPhysicalDevice();
|
||||
@@ -10,8 +13,8 @@ uint32_t GetVkGraphicsQueueFamily();
|
||||
VkFormat GetVkFormat();
|
||||
VkCommandBuffer GetVkCommandBuffer();
|
||||
void SubmitRequestedVkCommandBuffer();
|
||||
void LoadParallelRdp();
|
||||
void UpdateScreenParallelRdp();
|
||||
void LoadParallelRDP(const u8* rdram);
|
||||
void UpdateScreenParallelRdp(natsukashii::n64::core::VI& vi);
|
||||
void ParallelRdpEnqueueCommand(int command_length, u32* buffer);
|
||||
void ParallelRdpOnFullSync();
|
||||
void UpdateScreenParallelRdpNoGame();
|
||||
|
||||
Reference in New Issue
Block a user