Skip to content

Commit

Permalink
MythNVDECInterop: Add a workaround for context creation failure
Browse files Browse the repository at this point in the history
- untested, as having seen this again this morning, I can't reproduce it
again.
- also adds a thread safety check
  • Loading branch information
mark-kendall committed Feb 12, 2020
1 parent 5157ed0 commit 16c27a8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
39 changes: 36 additions & 3 deletions mythtv/libs/libmythtv/opengl/mythnvdecinterop.cpp
Expand Up @@ -4,6 +4,10 @@
#include "videocolourspace.h"
#include "mythnvdecinterop.h"

// Std
#include <chrono>
#include <thread>

#define LOC QString("NVDECInterop: ")

#define CUDA_CHECK(CUDA_FUNCS, CUDA_CALL) \
Expand Down Expand Up @@ -304,9 +308,10 @@ bool MythNVDECInterop::InitialiseCuda(void)
return CreateCUDAContext(m_context, m_cudaFuncs, m_cudaContext);
}

bool MythNVDECInterop::CreateCUDAContext(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs,
CUcontext &CudaContext)
bool MythNVDECInterop::CreateCUDAPriv(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs,
CUcontext &CudaContext, bool &Retry)
{
Retry = false;
if (!GLContext)
return false;

Expand Down Expand Up @@ -347,19 +352,47 @@ bool MythNVDECInterop::CreateCUDAContext(MythRenderOpenGL *GLContext, CudaFuncti
res = CudaFuncs->cuCtxCreate(&CudaContext, CU_CTX_SCHED_BLOCKING_SYNC, cudevice);
if (res != CUDA_SUCCESS)
{
LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create CUDA context");
LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to create CUDA context (Err: %1)")
.arg(res));
Retry = true;
return false;
}

CudaFuncs->cuCtxPopCurrent(&dummy);
LOG(VB_PLAYBACK, LOG_INFO, LOC + "Created CUDA context");
return true;
}

bool MythNVDECInterop::CreateCUDAContext(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs,
CUcontext &CudaContext)
{
if (!gCoreContext->IsUIThread())
{
LOG(VB_GENERAL, LOG_ERR, LOC + "Must create CUDA context from main thread");
return false;
}

int retries = 0;
bool retry = false;
while (retries++ < 5)
{
if (CreateCUDAPriv(GLContext, CudaFuncs, CudaContext, retry))
return true;
CleanupContext(GLContext, CudaFuncs, CudaContext);
if (!retry)
break;
LOG(VB_GENERAL, LOG_WARNING, LOC + "Will retry in 50ms");
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
return false;
}

void MythNVDECInterop::CleanupContext(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs,
CUcontext &CudaContext)
{
if (!GLContext)
return;

OpenGLLocker locker(GLContext);
if (CudaFuncs)
{
Expand Down
3 changes: 2 additions & 1 deletion mythtv/libs/libmythtv/opengl/mythnvdecinterop.h
Expand Up @@ -35,7 +35,8 @@ class MythNVDECInterop : public MythOpenGLInterop
bool InitialiseCuda(void);
void DeleteTextures(void) override;
void RotateReferenceFrames(CUdeviceptr Buffer);

static bool CreateCUDAPriv(MythRenderOpenGL *GLContext, CudaFunctions *&CudaFuncs,
CUcontext &CudaContext, bool &Retry);
CUcontext m_cudaContext;
CudaFunctions *m_cudaFuncs { nullptr };
QVector<CUdeviceptr> m_referenceFrames;
Expand Down

0 comments on commit 16c27a8

Please sign in to comment.