diff options
Diffstat (limited to 'intern/cycles/hydra/display_driver.cpp')
-rw-r--r-- | intern/cycles/hydra/display_driver.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/intern/cycles/hydra/display_driver.cpp b/intern/cycles/hydra/display_driver.cpp new file mode 100644 index 00000000000..6f6ca35cd31 --- /dev/null +++ b/intern/cycles/hydra/display_driver.cpp @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2022 NVIDIA Corporation + * Copyright 2022 Blender Foundation */ + +#ifdef _WIN32 +// Include first to avoid "NOGDI" definition set in Cycles headers +# include <Windows.h> +#endif + +#include "hydra/display_driver.h" +#include "hydra/render_buffer.h" +#include "hydra/session.h" + +#include <GL/glew.h> +#include <pxr/imaging/hgiGL/texture.h> + +HDCYCLES_NAMESPACE_OPEN_SCOPE + +HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *hgi) + : _renderParam(renderParam), _hgi(hgi) +{ +#ifdef _WIN32 + hdc_ = GetDC(CreateWindowA("STATIC", + "HdCycles", + WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, + 0, + 64, + 64, + NULL, + NULL, + GetModuleHandle(NULL), + NULL)); + + int pixelFormat = GetPixelFormat(wglGetCurrentDC()); + PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd)}; + DescribePixelFormat((HDC)hdc_, pixelFormat, sizeof(pfd), &pfd); + SetPixelFormat((HDC)hdc_, pixelFormat, &pfd); + + TF_VERIFY(gl_context_ = wglCreateContext((HDC)hdc_)); + TF_VERIFY(wglShareLists(wglGetCurrentContext(), (HGLRC)gl_context_)); +#endif + + glewInit(); + + glGenBuffers(1, &gl_pbo_id_); +} + +HdCyclesDisplayDriver::~HdCyclesDisplayDriver() +{ + if (texture_) { + _hgi->DestroyTexture(&texture_); + } + + glDeleteBuffers(1, &gl_pbo_id_); + +#ifdef _WIN32 + TF_VERIFY(wglDeleteContext((HGLRC)gl_context_)); + DestroyWindow(WindowFromDC((HDC)hdc_)); +#endif +} + +void HdCyclesDisplayDriver::next_tile_begin() +{ +} + +bool HdCyclesDisplayDriver::update_begin(const Params ¶ms, + int texture_width, + int texture_height) +{ +#ifdef _WIN32 + if (!hdc_ || !gl_context_) { + return false; + } +#endif + + graphics_interop_activate(); + + if (gl_render_sync_) { + glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED); + } + + if (pbo_size_.x != params.full_size.x || pbo_size_.y != params.full_size.y) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_); + glBufferData(GL_PIXEL_UNPACK_BUFFER, + sizeof(half4) * params.full_size.x * params.full_size.y, + 0, + GL_DYNAMIC_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + pbo_size_ = params.full_size; + } + + need_update_ = true; + + return true; +} + +void HdCyclesDisplayDriver::update_end() +{ + gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + + glFlush(); + + graphics_interop_deactivate(); +} + +void HdCyclesDisplayDriver::flush() +{ + graphics_interop_activate(); + + if (gl_upload_sync_) { + glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED); + } + + if (gl_render_sync_) { + glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED); + } + + graphics_interop_deactivate(); +} + +half4 *HdCyclesDisplayDriver::map_texture_buffer() +{ + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_); + + const auto mapped_rgba_pixels = static_cast<half4 *>( + glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); + + if (need_clear_ && mapped_rgba_pixels) { + memset(mapped_rgba_pixels, 0, sizeof(half4) * pbo_size_.x * pbo_size_.y); + need_clear_ = false; + } + + return mapped_rgba_pixels; +} + +void HdCyclesDisplayDriver::unmap_texture_buffer() +{ + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + +DisplayDriver::GraphicsInterop HdCyclesDisplayDriver::graphics_interop_get() +{ + GraphicsInterop interop_dst; + interop_dst.buffer_width = pbo_size_.x; + interop_dst.buffer_height = pbo_size_.y; + interop_dst.opengl_pbo_id = gl_pbo_id_; + + interop_dst.need_clear = need_clear_; + need_clear_ = false; + + return interop_dst; +} + +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 +} + +void HdCyclesDisplayDriver::graphics_interop_deactivate() +{ +#ifdef _WIN32 + if (wglGetCurrentContext() == gl_context_) { + TF_VERIFY(wglMakeCurrent(nullptr, nullptr)); + } +#endif + + mutex_.unlock(); +} + +void HdCyclesDisplayDriver::clear() +{ + need_clear_ = true; +} + +void HdCyclesDisplayDriver::draw(const Params ¶ms) +{ + const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>( + _renderParam->GetDisplayAovBinding().renderBuffer); + if (!renderBuffer || // Ensure this render buffer matches the texture dimensions + (renderBuffer->GetWidth() != params.size.x || renderBuffer->GetHeight() != params.size.y)) { + return; + } + + // Cycles 'DisplayDriver' only supports 'half4' format + TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4); + + const thread_scoped_lock lock(mutex_); + + const GfVec3i dimensions(params.size.x, params.size.y, 1); + if (!texture_ || texture_->GetDescriptor().dimensions != dimensions) { + if (texture_) { + _hgi->DestroyTexture(&texture_); + } + + HgiTextureDesc texDesc; + texDesc.usage = 0; + texDesc.format = HgiFormatFloat16Vec4; + texDesc.type = HgiTextureType2D; + texDesc.dimensions = dimensions; + texDesc.sampleCount = HgiSampleCount1; + + texture_ = _hgi->CreateTexture(texDesc); + + renderBuffer->SetResource(VtValue(texture_)); + } + + HgiGLTexture *const texture = dynamic_cast<HgiGLTexture *>(texture_.Get()); + if (!texture || !need_update_ || pbo_size_.x != params.size.x || pbo_size_.y != params.size.y) { + return; + } + + if (gl_upload_sync_) { + glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED); + } + + glBindTexture(GL_TEXTURE_2D, texture->GetTextureId()); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo_id_); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pbo_size_.x, pbo_size_.y, GL_RGBA, GL_HALF_FLOAT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + + glFlush(); + + need_update_ = false; +} + +HDCYCLES_NAMESPACE_CLOSE_SCOPE |