Fix use of OpenGL interop breaking in Hydra viewports that do not support it
Rendering directly to a resource using OpenGL interop and Hgi doesn't work in Houdini, since it never uses the resulting resource (it does not call `HdRenderBuffer::GetResource`). But since doing that simultaneously disables mapping (`HdRenderBuffer::Map` is not implemented then), nothing was displayed. To fix this, keep track of whether a Hydra viewport does support displaying a Hgi resource directly, by checking whether `HdRenderBuffer::GetResource` is ever called and only enable use of OpenGL interop if that is the case. Differential Revision: https://developer.blender.org/D15090
This commit is contained in:
parent
7f7ed8e098
commit
34f94a02f3
|
@ -23,10 +23,18 @@ HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *
|
|||
|
||||
HdCyclesDisplayDriver::~HdCyclesDisplayDriver()
|
||||
{
|
||||
deinit();
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
}
|
||||
|
||||
if (gl_pbo_id_) {
|
||||
glDeleteBuffers(1, &gl_pbo_id_);
|
||||
}
|
||||
|
||||
gl_context_dispose();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::init()
|
||||
void HdCyclesDisplayDriver::gl_context_create()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!gl_context_) {
|
||||
|
@ -64,16 +72,42 @@ void HdCyclesDisplayDriver::init()
|
|||
}
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::deinit()
|
||||
bool HdCyclesDisplayDriver::gl_context_enable()
|
||||
{
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
#ifdef _WIN32
|
||||
if (!hdc_ || !gl_context_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gl_pbo_id_) {
|
||||
glDeleteBuffers(1, &gl_pbo_id_);
|
||||
mutex_.lock();
|
||||
|
||||
// Do not change context if this is called in the main thread
|
||||
if (wglGetCurrentContext() == nullptr) {
|
||||
if (!TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_))) {
|
||||
mutex_.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::gl_context_disable()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wglGetCurrentContext() == gl_context_) {
|
||||
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
|
||||
}
|
||||
|
||||
mutex_.unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::gl_context_dispose()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (gl_context_) {
|
||||
TF_VERIFY(wglDeleteContext((HGLRC)gl_context_));
|
||||
|
@ -90,13 +124,9 @@ bool HdCyclesDisplayDriver::update_begin(const Params ¶ms,
|
|||
int texture_width,
|
||||
int texture_height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!hdc_ || !gl_context_) {
|
||||
if (!gl_context_enable()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
graphics_interop_activate();
|
||||
|
||||
if (gl_render_sync_) {
|
||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
|
@ -121,15 +151,14 @@ bool HdCyclesDisplayDriver::update_begin(const Params ¶ms,
|
|||
void HdCyclesDisplayDriver::update_end()
|
||||
{
|
||||
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
graphics_interop_deactivate();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::flush()
|
||||
{
|
||||
graphics_interop_activate();
|
||||
gl_context_enable();
|
||||
|
||||
if (gl_upload_sync_) {
|
||||
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
|
@ -139,7 +168,7 @@ void HdCyclesDisplayDriver::flush()
|
|||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
graphics_interop_deactivate();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
half4 *HdCyclesDisplayDriver::map_texture_buffer()
|
||||
|
@ -179,25 +208,12 @@ DisplayDriver::GraphicsInterop HdCyclesDisplayDriver::graphics_interop_get()
|
|||
|
||||
void HdCyclesDisplayDriver::graphics_interop_activate()
|
||||
{
|
||||
mutex_.lock();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Do not change context if this is called in the main thread
|
||||
if (wglGetCurrentContext() == nullptr) {
|
||||
TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_));
|
||||
}
|
||||
#endif
|
||||
gl_context_enable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::graphics_interop_deactivate()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wglGetCurrentContext() == gl_context_) {
|
||||
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_.unlock();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::clear()
|
||||
|
@ -214,7 +230,11 @@ void HdCyclesDisplayDriver::draw(const Params ¶ms)
|
|||
return;
|
||||
}
|
||||
|
||||
init();
|
||||
if (!renderBuffer->IsResourceUsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_context_create();
|
||||
|
||||
// Cycles 'DisplayDriver' only supports 'half4' format
|
||||
TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4);
|
||||
|
@ -255,7 +275,6 @@ void HdCyclesDisplayDriver::draw(const Params ¶ms)
|
|||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
need_update_ = false;
|
||||
|
|
|
@ -19,9 +19,6 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
~HdCyclesDisplayDriver();
|
||||
|
||||
private:
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
void next_tile_begin() override;
|
||||
|
||||
bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||
|
@ -41,6 +38,11 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
|
||||
void draw(const Params ¶ms) override;
|
||||
|
||||
void gl_context_create();
|
||||
bool gl_context_enable();
|
||||
void gl_context_disable();
|
||||
void gl_context_dispose();
|
||||
|
||||
HdCyclesSession *const _renderParam;
|
||||
Hgi *const _hgi;
|
||||
|
||||
|
@ -48,7 +50,6 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
void *hdc_ = nullptr;
|
||||
void *gl_context_ = nullptr;
|
||||
#endif
|
||||
|
||||
CCL_NS::thread_mutex mutex_;
|
||||
|
||||
PXR_NS::HgiTextureHandle texture_;
|
||||
|
|
|
@ -30,11 +30,11 @@ bool HdCyclesOutputDriver::update_render_tile(const Tile &tile)
|
|||
std::vector<float> pixels;
|
||||
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (aovBinding == _renderParam->GetDisplayAovBinding()) {
|
||||
continue; // Display AOV binding is already updated by Cycles display driver
|
||||
}
|
||||
|
||||
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
|
||||
if (aovBinding == _renderParam->GetDisplayAovBinding() && renderBuffer->IsResourceUsed()) {
|
||||
continue; // Display AOV binding is already updated by Cycles display driver
|
||||
}
|
||||
|
||||
const HdFormat format = renderBuffer->GetFormat();
|
||||
if (format == HdFormatInvalid) {
|
||||
continue; // Skip invalid AOV bindings
|
||||
|
|
|
@ -35,7 +35,7 @@ bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format,
|
|||
return false;
|
||||
}
|
||||
|
||||
const size_t oldSize = _data.size();
|
||||
const size_t oldSize = _dataSize;
|
||||
const size_t newSize = dimensions[0] * dimensions[1] * HdDataSizeOfFormat(format);
|
||||
if (oldSize == newSize) {
|
||||
return true;
|
||||
|
@ -49,8 +49,8 @@ bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format,
|
|||
_width = dimensions[0];
|
||||
_height = dimensions[1];
|
||||
_format = format;
|
||||
|
||||
_data.resize(newSize);
|
||||
_dataSize = newSize;
|
||||
_resourceUsed = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ void HdCyclesRenderBuffer::_Deallocate()
|
|||
|
||||
_data.clear();
|
||||
_data.shrink_to_fit();
|
||||
_dataSize = 0;
|
||||
|
||||
_resource = VtValue();
|
||||
}
|
||||
|
@ -74,6 +75,10 @@ void *HdCyclesRenderBuffer::Map()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (_data.size() != _dataSize) {
|
||||
_data.resize(_dataSize);
|
||||
}
|
||||
|
||||
++_mapped;
|
||||
|
||||
return _data.data();
|
||||
|
@ -103,10 +108,17 @@ void HdCyclesRenderBuffer::SetConverged(bool converged)
|
|||
_converged = converged;
|
||||
}
|
||||
|
||||
bool HdCyclesRenderBuffer::IsResourceUsed() const
|
||||
{
|
||||
return _resourceUsed;
|
||||
}
|
||||
|
||||
VtValue HdCyclesRenderBuffer::GetResource(bool multiSampled) const
|
||||
{
|
||||
TF_UNUSED(multiSampled);
|
||||
|
||||
_resourceUsed = true;
|
||||
|
||||
return _resource;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
|
|||
|
||||
void SetConverged(bool converged);
|
||||
|
||||
bool IsResourceUsed() const;
|
||||
|
||||
PXR_NS::VtValue GetResource(bool multiSampled = false) const override;
|
||||
|
||||
void SetResource(const PXR_NS::VtValue &resource);
|
||||
|
@ -74,9 +76,11 @@ class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
|
|||
unsigned int _width = 0u;
|
||||
unsigned int _height = 0u;
|
||||
PXR_NS::HdFormat _format = PXR_NS::HdFormatInvalid;
|
||||
size_t _dataSize = 0;
|
||||
|
||||
std::vector<uint8_t> _data;
|
||||
PXR_NS::VtValue _resource;
|
||||
mutable std::atomic_bool _resourceUsed = false;
|
||||
|
||||
std::atomic_int _mapped = 0;
|
||||
std::atomic_bool _converged = false;
|
||||
|
|
Loading…
Reference in New Issue