server: fix software rendering
It was broken
This commit is contained in:
parent
2e4e810e5f
commit
efc2800358
1 changed files with 77 additions and 7 deletions
|
@ -4,6 +4,7 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use cudarc::driver::sys::CUmemorytype;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -185,9 +186,12 @@ impl RetroState {
|
||||||
|
|
||||||
let has_disconnected_pitch = pitch != size.width as u32;
|
let has_disconnected_pitch = pitch != size.width as u32;
|
||||||
|
|
||||||
for y in 0..size.height {
|
for _y in 0..size.height {
|
||||||
|
// Trick to flip the buffer the way OpenGL likes.
|
||||||
|
let y = (size.height - 1) - _y;
|
||||||
|
|
||||||
let src_line_off = (y as u32 * pitch) as usize;
|
let src_line_off = (y as u32 * pitch) as usize;
|
||||||
let mut dest_line_off = (y as u32 * size.width) as usize;
|
let mut dest_line_off = (_y as u32 * size.width) as usize;
|
||||||
|
|
||||||
// copy only
|
// copy only
|
||||||
if has_disconnected_pitch {
|
if has_disconnected_pitch {
|
||||||
|
@ -224,7 +228,10 @@ impl FrontendInterface for RetroState {
|
||||||
.lock()
|
.lock()
|
||||||
.expect("Failed to lock CUDA resource");
|
.expect("Failed to lock CUDA resource");
|
||||||
|
|
||||||
locked.device().bind_to_thread().expect("Failed to bind CUDA device to thread");
|
locked
|
||||||
|
.device()
|
||||||
|
.bind_to_thread()
|
||||||
|
.expect("Failed to bind CUDA device to thread");
|
||||||
|
|
||||||
locked
|
locked
|
||||||
.register(self.gl_framebuffer.texture_id(), gl::TEXTURE_2D)
|
.register(self.gl_framebuffer.texture_id(), gl::TEXTURE_2D)
|
||||||
|
@ -242,18 +249,78 @@ impl FrontendInterface for RetroState {
|
||||||
let size = self.software_framebuffer.size.clone();
|
let size = self.software_framebuffer.size.clone();
|
||||||
|
|
||||||
// upload texture to GPU
|
// upload texture to GPU
|
||||||
unsafe {
|
/*unsafe {
|
||||||
|
tracing::info!("bind tex");
|
||||||
|
gl::BindTexture(gl::TEXTURE_2D, self.gl_framebuffer.texture_id());
|
||||||
|
|
||||||
|
tracing::info!("upload");
|
||||||
gl::TexImage2D(
|
gl::TexImage2D(
|
||||||
gl::TEXTURE_2D,
|
gl::TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
gl::RGBA as i32,
|
gl::RGBA8 as i32,
|
||||||
size.width as i32,
|
size.width as i32,
|
||||||
size.height as i32,
|
size.height as i32,
|
||||||
0,
|
0,
|
||||||
gl::RGBA_INTEGER,
|
gl::RGBA,
|
||||||
gl::UNSIGNED_INT_8_8_8_8,
|
gl::UNSIGNED_BYTE,
|
||||||
self.software_framebuffer.get_buffer().as_mut_ptr() as *const _,
|
self.software_framebuffer.get_buffer().as_mut_ptr() as *const _,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tracing::info!("unbind tex");
|
||||||
|
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// TODO: Figure out a way to do this with standard OpenGL primitives.
|
||||||
|
// (the above does not work *at all*. Don't ask how I know)
|
||||||
|
unsafe {
|
||||||
|
let mut cuda_resource = self
|
||||||
|
.cuda_resource
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock CUDA resource");
|
||||||
|
|
||||||
|
cuda_resource
|
||||||
|
.device()
|
||||||
|
.bind_to_thread()
|
||||||
|
.expect("Failed to bind CUDA device to thread");
|
||||||
|
|
||||||
|
let mut mapped_cuda_resource = cuda_resource
|
||||||
|
.map()
|
||||||
|
.expect("Failed to map CUDA resource");
|
||||||
|
|
||||||
|
let array = mapped_cuda_resource
|
||||||
|
.get_mapped_array()
|
||||||
|
.expect("Failed to get CUarray from CUDA resource");
|
||||||
|
|
||||||
|
let mut memcpy = cudarc::driver::sys::CUDA_MEMCPY2D_st::default();
|
||||||
|
|
||||||
|
// src
|
||||||
|
memcpy.srcXInBytes = 0;
|
||||||
|
memcpy.srcY = 0;
|
||||||
|
memcpy.srcMemoryType = CUmemorytype::CU_MEMORYTYPE_HOST;
|
||||||
|
memcpy.srcHost = self.software_framebuffer.get_buffer().as_mut_ptr() as *const _;
|
||||||
|
|
||||||
|
// dest
|
||||||
|
memcpy.dstXInBytes = 0;
|
||||||
|
memcpy.dstY = 0;
|
||||||
|
memcpy.dstMemoryType = CUmemorytype::CU_MEMORYTYPE_ARRAY;
|
||||||
|
memcpy.dstArray = array;
|
||||||
|
|
||||||
|
memcpy.WidthInBytes = (size.width * 4) as usize;
|
||||||
|
memcpy.Height = size.height as usize;
|
||||||
|
memcpy.dstPitch = (size.width * 4) as usize;
|
||||||
|
|
||||||
|
// kick it off
|
||||||
|
cudarc::driver::sys::lib()
|
||||||
|
.cuMemcpy2DAsync_v2(&memcpy, std::ptr::null_mut())
|
||||||
|
.result()
|
||||||
|
.expect("cuMemcpy2D fail epic");
|
||||||
|
|
||||||
|
cudarc::driver::sys::lib()
|
||||||
|
.cuStreamSynchronize(std::ptr::null_mut())
|
||||||
|
.result()
|
||||||
|
.expect("fucking");
|
||||||
|
|
||||||
|
mapped_cuda_resource.unmap().expect("fuck you asshole");
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = self.event_tx.blocking_send(RetroEvent::Frame);
|
let _ = self.event_tx.blocking_send(RetroEvent::Frame);
|
||||||
|
@ -353,6 +420,9 @@ impl FrontendInterface for RetroState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hw_gl_init(&mut self) -> Option<HwGlInitData> {
|
fn hw_gl_init(&mut self) -> Option<HwGlInitData> {
|
||||||
|
// test SW-only even if a core wants to upgrade
|
||||||
|
//return None;
|
||||||
|
|
||||||
// Only create a new EGL/OpenGL context if we have to.
|
// Only create a new EGL/OpenGL context if we have to.
|
||||||
let context = self.egl_context.lock().expect("fuck you!");
|
let context = self.egl_context.lock().expect("fuck you!");
|
||||||
let extensions = gpu::egl_helpers::get_extensions(context.get_display());
|
let extensions = gpu::egl_helpers::get_extensions(context.get_display());
|
||||||
|
|
Loading…
Reference in a new issue