forked from LeenkxTeam/LNXRNT
Fix viewport
This commit is contained in:
@ -275,6 +275,11 @@ bool viewport_server_init(const char* shmem_name, int width, int height) {
|
||||
g_viewport_state.initialized = true;
|
||||
g_viewport_state.frame_count = 0;
|
||||
|
||||
#ifdef KINC_DIRECT3D11
|
||||
// disable vsync so the GPU queue flushes
|
||||
dx_ctx.windows[0].vsync = 0;
|
||||
#endif
|
||||
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "Viewport server initialized: %dx%d, shmem=%s",
|
||||
width, height, g_viewport_state.shmem_name);
|
||||
|
||||
@ -282,8 +287,10 @@ bool viewport_server_init(const char* shmem_name, int width, int height) {
|
||||
}
|
||||
|
||||
#ifdef KINC_DIRECT3D11
|
||||
static ID3D11Texture2D* g_stagingTexture = NULL;
|
||||
static ID3D11Texture2D* g_stagingTextures[2] = {NULL, NULL};
|
||||
static int g_stagingWidth = 0, g_stagingHeight = 0;
|
||||
static int g_stagingWriteIdx = 0;
|
||||
static bool g_stagingHasData[2] = {false, false};
|
||||
#endif
|
||||
|
||||
void viewport_server_shutdown(void) {
|
||||
@ -292,12 +299,16 @@ void viewport_server_shutdown(void) {
|
||||
}
|
||||
|
||||
#ifdef KINC_DIRECT3D11
|
||||
if (g_stagingTexture) {
|
||||
g_stagingTexture->Release();
|
||||
g_stagingTexture = NULL;
|
||||
g_stagingWidth = 0;
|
||||
g_stagingHeight = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (g_stagingTextures[i]) {
|
||||
g_stagingTextures[i]->Release();
|
||||
g_stagingTextures[i] = NULL;
|
||||
g_stagingHasData[i] = false;
|
||||
}
|
||||
}
|
||||
g_stagingWidth = 0;
|
||||
g_stagingHeight = 0;
|
||||
g_stagingWriteIdx = 0;
|
||||
#endif
|
||||
|
||||
#if !defined(KINC_DIRECT3D11) && !defined(KINC_OPENGL)
|
||||
@ -347,12 +358,19 @@ void viewport_server_end_frame(void) {
|
||||
|
||||
SharedFramebufferHeader* header = (SharedFramebufferHeader*)g_viewport_state.shmem_ptr;
|
||||
|
||||
// Drop-frame guard so that if blender hasnt consumed the previous frame it skip writeback
|
||||
if (header->ready_flag == 1) {
|
||||
g_viewport_state.frame_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
header->width = g_viewport_state.width;
|
||||
header->height = g_viewport_state.height;
|
||||
|
||||
size_t pixel_size = (size_t)g_viewport_state.width * g_viewport_state.height * 4;
|
||||
uint8_t* pixels = g_viewport_state.pixel_buffer;
|
||||
uint8_t* pixel_dest = (uint8_t*)g_viewport_state.shmem_ptr + VIEWPORT_HEADER_SIZE;
|
||||
bool pixels_written = false;
|
||||
|
||||
#ifdef KINC_DIRECT3D11
|
||||
// Direct3D11 - read from backbuffer BEFORE swap_buffers
|
||||
@ -378,10 +396,20 @@ void viewport_server_end_frame(void) {
|
||||
header->height = captureHeight;
|
||||
pixel_size = (size_t)captureWidth * captureHeight * 4;
|
||||
|
||||
// same dimensions between source and destination
|
||||
if (!g_stagingTexture || g_stagingWidth != bbWidth || g_stagingHeight != bbHeight) {
|
||||
if (g_stagingTexture) g_stagingTexture->Release();
|
||||
|
||||
// textures dimensions changed
|
||||
if (g_stagingWidth != bbWidth || g_stagingHeight != bbHeight) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (g_stagingTextures[i]) {
|
||||
g_stagingTextures[i]->Release();
|
||||
g_stagingTextures[i] = NULL;
|
||||
g_stagingHasData[i] = false;
|
||||
}
|
||||
}
|
||||
g_stagingWidth = bbWidth;
|
||||
g_stagingHeight = bbHeight;
|
||||
}
|
||||
|
||||
if (!g_stagingTextures[0] || !g_stagingTextures[1]) {
|
||||
D3D11_TEXTURE2D_DESC desc = {};
|
||||
desc.Width = bbWidth;
|
||||
desc.Height = bbHeight;
|
||||
@ -392,38 +420,46 @@ void viewport_server_end_frame(void) {
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
|
||||
HRESULT hr = device->CreateTexture2D(&desc, NULL, &g_stagingTexture);
|
||||
if (FAILED(hr)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create staging texture: 0x%08X", hr);
|
||||
g_stagingTexture = NULL;
|
||||
g_stagingWidth = 0;
|
||||
g_stagingHeight = 0;
|
||||
g_viewport_state.frame_count++;
|
||||
return;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!g_stagingTextures[i]) {
|
||||
HRESULT hr = device->CreateTexture2D(&desc, NULL, &g_stagingTextures[i]);
|
||||
if (FAILED(hr)) {
|
||||
g_stagingTextures[i] = NULL;
|
||||
g_viewport_state.frame_count++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_stagingWidth = bbWidth;
|
||||
g_stagingHeight = bbHeight;
|
||||
}
|
||||
|
||||
context->CopyResource(g_stagingTexture, backBuffer);
|
||||
int writeIdx = g_stagingWriteIdx;
|
||||
context->CopyResource(g_stagingTextures[writeIdx], backBuffer);
|
||||
g_stagingHasData[writeIdx] = true;
|
||||
|
||||
// only read the portion we need
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
if (SUCCEEDED(context->Map(g_stagingTexture, 0, D3D11_MAP_READ, 0, &mapped))) {
|
||||
for (int y = 0; y < captureHeight; y++) {
|
||||
memcpy(pixels + y * captureWidth * 4,
|
||||
(uint8_t*)mapped.pData + y * mapped.RowPitch,
|
||||
captureWidth * 4);
|
||||
int readIdx = writeIdx ^ 1;
|
||||
if (g_stagingHasData[readIdx]) {
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
HRESULT hr = context->Map(g_stagingTextures[readIdx], 0, D3D11_MAP_READ, D3D11_MAP_FLAG_DO_NOT_WAIT, &mapped);
|
||||
if (hr == DXGI_ERROR_WAS_STILL_DRAWING) {
|
||||
hr = context->Map(g_stagingTextures[readIdx], 0, D3D11_MAP_READ, 0, &mapped);
|
||||
}
|
||||
context->Unmap(g_stagingTexture, 0);
|
||||
|
||||
// BGRA to RGBA conversion
|
||||
for (size_t i = 0; i < pixel_size; i += 4) {
|
||||
uint8_t t = pixels[i]; pixels[i] = pixels[i+2]; pixels[i+2] = t;
|
||||
if (SUCCEEDED(hr)) {
|
||||
for (int y = 0; y < captureHeight; y++) {
|
||||
uint8_t* src = (uint8_t*)mapped.pData + y * mapped.RowPitch;
|
||||
uint8_t* dst = pixel_dest + y * captureWidth * 4;
|
||||
for (int x = 0; x < captureWidth * 4; x += 4) {
|
||||
dst[x] = src[x + 2]; // R <- B
|
||||
dst[x + 1] = src[x + 1]; // G
|
||||
dst[x + 2] = src[x]; // B <- R
|
||||
dst[x + 3] = src[x + 3]; // A
|
||||
}
|
||||
}
|
||||
context->Unmap(g_stagingTextures[readIdx], 0);
|
||||
pixels_written = true;
|
||||
}
|
||||
|
||||
memcpy(pixel_dest, pixels, pixel_size);
|
||||
}
|
||||
|
||||
g_stagingWriteIdx = writeIdx ^ 1;
|
||||
}
|
||||
//#elif defined(KINC_OPENGL)
|
||||
// glReadPixels(0, 0, g_viewport_state.width, g_viewport_state.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
@ -444,10 +480,16 @@ void viewport_server_end_frame(void) {
|
||||
kinc_g4_render_target_t* rt = (kinc_g4_render_target_t*)g_viewport_state.render_target;
|
||||
kinc_g4_render_target_get_pixels(rt, pixels);
|
||||
memcpy(pixel_dest, pixels, pixel_size);
|
||||
pixels_written = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_viewport_state.frame_count++;
|
||||
|
||||
if (!pixels_written) {
|
||||
return;
|
||||
}
|
||||
|
||||
header->frame_id = g_viewport_state.frame_count;
|
||||
|
||||
// NOTE: Camera sync from RunT to Blender is handled via viewport_server_set_camera()
|
||||
|
||||
Reference in New Issue
Block a user