Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video Routing Revamp #1323

Merged
merged 3 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
url = https://github.com/google/oboe.git
[submodule "core/deps/Syphon"]
path = core/deps/Syphon
url=https://github.com/vkedwardli/Syphon-Framework.git
url = https://github.com/vkedwardli/Syphon-Framework.git
[submodule "core/deps/Spout"]
path = core/deps/Spout
url = https://github.com/vkedwardli/Spout2.git
2 changes: 1 addition & 1 deletion core/deps/Spout
Submodule Spout updated 298 files
5 changes: 5 additions & 0 deletions core/rend/dx11/dx11_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,11 @@ void DX11Renderer::renderVideoRouting()
backBufferTexture->Release();
pResource->Release();
}
else
{
extern void os_VideoRoutingTermDX();
os_VideoRoutingTermDX();
}
#endif
}

Expand Down
15 changes: 0 additions & 15 deletions core/rend/dx11/dx11context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ bool DX11Context::init(bool keepCurrentWindow)
NOTICE_LOG(RENDERER, "No system-provided shader cache");
}

initVideoRouting();

imguiDriver = std::unique_ptr<ImGuiDriver>(new DX11Driver(pDevice, pDeviceContext));
resize();
shaders.init(pDevice, &D3DCompile);
Expand All @@ -190,19 +188,6 @@ bool DX11Context::init(bool keepCurrentWindow)
return success;
}

void DX11Context::initVideoRouting()
{
#ifdef VIDEO_ROUTING
extern void os_VideoRoutingTermDX();
extern void os_VideoRoutingInitSpoutDXWithDevice(ID3D11Device* pDevice);
os_VideoRoutingTermDX();
if (config::VideoRouting)
{
os_VideoRoutingInitSpoutDXWithDevice(pDevice.get());
}
#endif
}

void DX11Context::term()
{
NOTICE_LOG(RENDERER, "DX11 Context terminating");
Expand Down
1 change: 0 additions & 1 deletion core/rend/dx11/dx11context.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class DX11Context : public GraphicsContext
{
public:
bool init(bool keepCurrentWindow = false);
void initVideoRouting() override;
void term() override;
void EndImGuiFrame();
void Present();
Expand Down
5 changes: 5 additions & 0 deletions core/rend/gles/gles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,11 @@ void OpenGLRenderer::renderVideoRouting()
extern void os_VideoRoutingPublishFrameTexture(GLuint texID, GLuint texTarget, float w, float h);
os_VideoRoutingPublishFrameTexture(gl.videorouting.framebuffer->getTexture(), GL_TEXTURE_2D, targetWidth, targetHeight);
}
else
{
extern void os_VideoRoutingTermGL();
os_VideoRoutingTermGL();
}
#endif
}

Expand Down
17 changes: 6 additions & 11 deletions core/rend/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2241,24 +2241,19 @@ static void gui_display_settings()
((renderApi == 0) || (renderApi == 3)) ? header("Video Routing (Spout)") : header("Video Routing (Only available with OpenGL or DirectX 11)");
#endif
{
#ifdef __APPLE__
if (OptionCheckbox("Send video content to another application", config::VideoRouting,
"e.g. Route GPU texture to OBS Studio directly instead of using CPU intensive Display/Window Capture"))
#elif defined(_WIN32)
DisabledScope scope( !( (renderApi == 0) || (renderApi == 3)) );
if (OptionCheckbox("Send video content to another program", config::VideoRouting,
"e.g. Route GPU texture to OBS Studio directly instead of using CPU intensive Display/Window Capture"))
#ifdef _WIN32
DisabledScope scope(!((renderApi == 0) || (renderApi == 3)));
#endif
{
GraphicsContext::Instance()->initVideoRouting();
}
OptionCheckbox("Send video content to another program", config::VideoRouting,
"e.g. Route GPU texture to OBS Studio directly instead of using CPU intensive Display/Window Capture");

{
DisabledScope scope(!config::VideoRouting);
OptionCheckbox("Scale down before sending", config::VideoRoutingScale, "Could increase performance when sharing a smaller texture, YMMV");
{
DisabledScope scope(!config::VideoRoutingScale);
static int vres = config::VideoRoutingVRes;
if( ImGui::InputInt("Output vertical resolution", &vres) )
if (ImGui::InputInt("Output vertical resolution", &vres))
{
config::VideoRoutingVRes = vres;
}
Expand Down
15 changes: 0 additions & 15 deletions core/rend/vulkan/vulkan_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,6 @@ bool VulkanContext::InitDevice()
+ std::to_string(props.driverVersion / 10000) + "."
+ std::to_string((props.driverVersion % 10000) / 100) + "."
+ std::to_string(props.driverVersion % 100);

initVideoRouting();
#else
driverVersion = std::to_string(VK_API_VERSION_MAJOR(props.driverVersion)) + "."
+ std::to_string(VK_API_VERSION_MINOR(props.driverVersion)) + "."
Expand All @@ -513,19 +511,6 @@ bool VulkanContext::InitDevice()
return false;
}

void VulkanContext::initVideoRouting()
{
#if defined(VIDEO_ROUTING) && defined(TARGET_MAC)
extern void os_VideoRoutingTermVk();
extern void os_VideoRoutingInitSyphonWithVkDevice(const vk::UniqueDevice& device);
os_VideoRoutingTermVk();
if (config::VideoRouting)
{
os_VideoRoutingInitSyphonWithVkDevice(device);
}
#endif
}

void VulkanContext::CreateSwapChain()
{
try
Expand Down
1 change: 0 additions & 1 deletion core/rend/vulkan/vulkan_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class VulkanContext : public GraphicsContext, public FlightManager
void Present() noexcept;
void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) noexcept;
void PresentLastFrame();
void initVideoRouting() override;

vk::PhysicalDevice GetPhysicalDevice() const { return physicalDevice; }
vk::Device GetDevice() const { return *device; }
Expand Down
46 changes: 25 additions & 21 deletions core/windows/winmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,21 +515,16 @@ void os_RunInstance(int argc, const char *argv[])
static SpoutSender* spoutSender;
static spoutDX* spoutDXSender;

void os_VideoRoutingInitSpout()
void os_VideoRoutingPublishFrameTexture(GLuint texID, GLuint texTarget, float w, float h)
{
if (spoutSender == nullptr)
{
spoutSender = new SpoutSender();
}

int boardID = cfgLoadInt("naomi", "BoardId", 0);
char buf[32] = {0};
vsnprintf(buf, sizeof(buf), (boardID == 0 ? "Flycast - Video Content" : "Flycast - Video Content - %d"), std::va_list(&boardID));
spoutSender->SetSenderName(buf);
}

void os_VideoRoutingPublishFrameTexture(GLuint texID, GLuint texTarget, float w, float h)
{
int boardID = cfgLoadInt("naomi", "BoardId", 0);
char buf[32] = { 0 };
vsnprintf(buf, sizeof(buf), (boardID == 0 ? "Flycast - Video Content" : "Flycast - Video Content - %d"), std::va_list(&boardID));
spoutSender->SetSenderName(buf);
}
spoutSender->SendTexture(texID, texTarget, w, h, true);
}

Expand All @@ -542,21 +537,30 @@ void os_VideoRoutingTermGL()
}
}

void os_VideoRoutingInitSpoutDXWithDevice(ID3D11Device* pDevice)
void os_VideoRoutingPublishFrameTexture(ID3D11Texture2D* pTexture)
{
if (spoutDXSender == nullptr)
{
spoutDXSender = new spoutDX();
ID3D11Resource* resource = nullptr;
HRESULT hr = pTexture->QueryInterface(__uuidof(ID3D11Resource), reinterpret_cast<void**>(&resource));
if (SUCCEEDED(hr))
{
ID3D11Device* pDevice = nullptr;
resource->GetDevice(&pDevice);
resource->Release();
spoutDXSender->OpenDirectX11(pDevice);
pDevice->Release();
int boardID = cfgLoadInt("naomi", "BoardId", 0);
char buf[32] = { 0 };
vsnprintf(buf, sizeof(buf), (boardID == 0 ? "Flycast - Video Content" : "Flycast - Video Content - %d"), std::va_list(&boardID));
spoutDXSender->SetSenderName(buf);
}
else
{
return;
}
}
spoutDXSender->OpenDirectX11(pDevice);
int boardID = cfgLoadInt("naomi", "BoardId", 0);
char buf[32] = {0};
vsnprintf(buf, sizeof(buf), (boardID == 0 ? "Flycast - Video Content" : "Flycast - Video Content - %d"), std::va_list(&boardID));
spoutDXSender->SetSenderName(buf);
}

void os_VideoRoutingPublishFrameTexture(ID3D11Texture2D* pTexture)
{
spoutDXSender->SendTexture(pTexture);
}

Expand Down
1 change: 0 additions & 1 deletion core/wsi/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class GraphicsContext
virtual std::string getDriverName() = 0;
virtual std::string getDriverVersion() = 0;
virtual bool hasPerPixel() { return false; }
virtual void initVideoRouting() {}

void setWindow(void *window, void *display = nullptr) {
this->window = window;
Expand Down
19 changes: 0 additions & 19 deletions core/wsi/sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,29 +108,10 @@ bool SDLGLGraphicsContext::init()
}
#endif
postInit();
initVideoRouting();

return true;
}

void SDLGLGraphicsContext::initVideoRouting()
{
#ifdef VIDEO_ROUTING
extern void os_VideoRoutingTermGL();
os_VideoRoutingTermGL();
if (config::VideoRouting)
{
#ifdef TARGET_MAC
extern void os_VideoRoutingInitSyphonWithGLContext(void* glContext);
os_VideoRoutingInitSyphonWithGLContext(glcontext);
#elif defined(_WIN32)
extern void os_VideoRoutingInitSpout();
os_VideoRoutingInitSpout();
#endif
}
#endif
}

void SDLGLGraphicsContext::swap()
{
do_swap_automation();
Expand Down
1 change: 0 additions & 1 deletion core/wsi/sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ class SDLGLGraphicsContext : public GLGraphicsContext
bool init();
void term() override;
void swap();
void initVideoRouting() override;

private:
SDL_GLContext glcontext = nullptr;
Expand Down
31 changes: 15 additions & 16 deletions shell/apple/emulator-osx/emulator-osx/osx-main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,13 @@ void os_RunInstance(int argc, const char *argv[])
static SyphonOpenGLServer* syphonGLServer;
static SyphonMetalServer* syphonMtlServer;

void os_VideoRoutingInitSyphonWithGLContext(void* glContext)
{
int boardID = cfgLoadInt("naomi", "BoardId", 0);
syphonGLServer = [[SyphonOpenGLServer alloc] initWithName:[NSString stringWithFormat:(boardID == 0 ? @"Video Content" : @"Video Content - %d"), boardID] context:[(__bridge NSOpenGLContext*)glContext CGLContextObj] options:nil];
}

void os_VideoRoutingPublishFrameTexture(GLuint texID, GLuint texTarget, float w, float h)
{
if (syphonGLServer == NULL)
{
int boardID = cfgLoadInt("naomi", "BoardId", 0);
syphonGLServer = [[SyphonOpenGLServer alloc] initWithName:[NSString stringWithFormat:(boardID == 0 ? @"Video Content" : @"Video Content - %d"), boardID] context:[SDL_GL_GetCurrentContext() CGLContextObj] options:nil];
}
CGLLockContext([syphonGLServer context]);
[syphonGLServer publishFrameTexture:texID textureTarget:texTarget imageRegion:NSMakeRect(0, 0, w, h) textureDimensions:NSMakeSize(w, h) flipped:NO];
CGLUnlockContext([syphonGLServer context]);
Expand All @@ -256,18 +255,18 @@ void os_VideoRoutingTermGL()
syphonGLServer = NULL;
}

void os_VideoRoutingInitSyphonWithVkDevice(const vk::UniqueDevice& device)
{
vk::ExportMetalDeviceInfoEXT deviceInfo;
auto objectsInfo = vk::ExportMetalObjectsInfoEXT(&deviceInfo);
device->exportMetalObjectsEXT(&objectsInfo);

int boardID = cfgLoadInt("naomi", "BoardId", 0);
syphonMtlServer = [[SyphonMetalServer alloc] initWithName:[NSString stringWithFormat:(boardID == 0 ? @"Video Content" : @"Video Content - %d"), boardID] device:deviceInfo.mtlDevice options:nil];
}

void os_VideoRoutingPublishFrameTexture(const vk::Device& device, const vk::Image& image, const vk::Queue& queue, float x, float y, float w, float h)
{
if (syphonMtlServer == NULL)
{
vk::ExportMetalDeviceInfoEXT deviceInfo;
auto objectsInfo = vk::ExportMetalObjectsInfoEXT(&deviceInfo);
device.exportMetalObjectsEXT(&objectsInfo);

int boardID = cfgLoadInt("naomi", "BoardId", 0);
syphonMtlServer = [[SyphonMetalServer alloc] initWithName:[NSString stringWithFormat:(boardID == 0 ? @"Video Content" : @"Video Content - %d"), boardID] device:deviceInfo.mtlDevice options:nil];
}

auto textureInfo = vk::ExportMetalTextureInfoEXT(image);
auto commandInfo = vk::ExportMetalCommandQueueInfoEXT(queue);
commandInfo.pNext = &textureInfo;
Expand Down