- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近一直在苦苦挣扎,因为我不得不更改我不久前编写的一些代码以在 Qt
中进行图像处理和 OpenGl
以支持多线程。
问题是我想用它在一组图像上应用批量过滤器,
我正在使用 openMP 来做这样的多线程:
void batchProcess(QVector<QImage> &images)
{
#pragma omp parallel
{
#pragma omp for schedule(dynamic) nowait
for (int i = 1; i < images.count(); i++)
{
images[i] = ImageProcessing::processImage(images[i], _vertexShader, _fragmentShader, _textureVar, _vertexPosVar, _textureCoordVar);
}
}
}
和
ImageProcessing::processImage()
函数看起来像这样:
QImage ImageProcessing::processImage(const QImage &source, const QString &vertexShader, const QString &fragmentShader, const QString &textureVar, const QString &vertexPosVar, const QString &textureCoordVar)
{
QOpenGLContext context;
if(!context.create())
return source;
QOffscreenSurface surface;
surface.setFormat(context.format());
surface.create();
if(!surface.isValid())
return source;
if(!context.makeCurrent(&surface))
return source;
QOpenGLFramebufferObject fbo(source.size());
context.functions()->glViewport(0, 0, source.width(), source.height());
QOpenGLShaderProgram program(&context);
if (!program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader))
return source;
if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader))
return source;
if (!program.link())
return source;
if (!program.bind())
return source;
QOpenGLTexture texture(QOpenGLTexture::Target2D);
texture.setData(source);
texture.bind();
if(!texture.isBound())
return source;
VertexData vertices[] =
{
{{ -1.0f, +1.0f }, { 0.0f, 1.0f }}, // top-left
{{ +1.0f, +1.0f }, { 1.0f, 1.0f }}, // top-right
{{ -1.0f, -1.0f }, { 0.0f, 0.0f }}, // bottom-left
{{ +1.0f, -1.0f }, { 1.0f, 0.0f }} // bottom-right
};
GLuint indices[] =
{
0, 1, 2, 3
};
QOpenGLBuffer vertexBuf(QOpenGLBuffer::VertexBuffer);
QOpenGLBuffer indexBuf(QOpenGLBuffer::IndexBuffer);
if(!vertexBuf.create())
return source;
if(!indexBuf.create())
return source;
if(!vertexBuf.bind())
return source;
vertexBuf.allocate(vertices, 4 * sizeof(VertexData));
if(!indexBuf.bind())
return source;
indexBuf.allocate(indices, 4 * sizeof(GLuint));
int offset = 0;
program.enableAttributeArray(vertexPosVar.toLatin1().data());
program.setAttributeBuffer(vertexPosVar.toLatin1().data(), GL_FLOAT, offset, 2, sizeof(VertexData));
offset += sizeof(QVector2D);
program.enableAttributeArray(textureCoordVar.toLatin1().data());
program.setAttributeBuffer(textureCoordVar.toLatin1().data(), GL_FLOAT, offset, 2, sizeof(VertexData));
program.setUniformValue(textureVar.toLatin1().data(), 0);
context.functions()->glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, Q_NULLPTR);
return fbo.toImage(false);
}
当
OpenMP
时它工作正常已禁用,但是当我启用它时,出现以下错误:
Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.
QOffscreenSurface
只是一个隐藏的
QWindow
在某些平台上,这意味着它只能从主线程创建或销毁。
QOffscreenSurface
在主线程中,我关注了这个
answer并实现了以下类
class OpenGlFilterPrivate : public QObject
{
Q_OBJECT
public:
enum CustomEventTypes
{
CreateSurface = QEvent::User,
CreateContext = QEvent::User + 1,
CreateProgram = QEvent::User + 2
};
void moveToMainThread()
{
moveToThread(QApplication::instance()->thread());
}
virtual bool event(QEvent *event )
{
switch (event->type())
{
case CreateSurface: // m_surface (create an offscreen surface from the main thread)
m_surface = QSharedPointer<QOffscreenSurface>::create();
m_surface->setFormat(m_context->format());
m_surface->create();
break;
case CreateContext: // m_context (create an openGl context from the main thread)
m_context = QSharedPointer<QOpenGLContext>::create();
break;
case CreateProgram: // m_shaderProgram (create an openGl shader program from the main thread)
m_shaderProgram = QSharedPointer<QOpenGLShaderProgram>::create(&*m_context);
}
return false;
}
QSharedPointer<QOpenGLContext> m_context;
QSharedPointer<QOffscreenSurface> m_surface;
QSharedPointer<QOpenGLShaderProgram> m_shaderProgram;
};
现在而不是直接创建一个
QOffscreenSurface
在我的
processImage
功能我执行以下操作:
OpenGlFilterPrivate openGlFilterPrivate;
openGlFilterPrivate.moveToMainThread();
QCoreApplication::postEvent(&openGlFilterPrivate, new QEvent(QEvent::Type(OpenGlFilterPrivate::CreateSurface)));
QSharedPointer<QOffscreenSurface> surface = openGlFilterPrivate.m_surface;
它有效,但现在我不断收到以下消息:
QObject::~QObject: Timers cannot be stopped from another thread
QObject
包含
QTimer
在内部,这就是导致问题的原因,但我想不出任何其他方法来解决这个问题。
openGl
应用一些图像处理过滤器或任何其他硬件加速方法,同时有能力在
thread-safe
中做到这一点道路。
QPainter
相同的方法来完成,它是线程安全的,据我所知,它是使用 OpenGL 进行硬件加速的。但我找不到关于如何做这样的事情的任何资源。 最佳答案
哦,我的,OpenMP 和 OpenGL 可能不能很好地混合。 OpenMP 创建多线程的方式并没有固定在 OpenGL 实现可以访问的方面。它很可能使用常规 POSIX 线程或 Windows native 线程。但它也可以是其他任何东西,在同一地址空间内创建额外的任务。
我认为创建一个由 N 个线程组成的池会更加健壮和容易,每个线程都有自己的共享 OpenGL 上下文,然后使用工作窃取来安排任务;使 OpenGL 在工作集之间的线程上保持最新状态。
使用现代 OpenGL 非常方便,甚至不需要窗口或类似的可绘制对象来使上下文成为当前状态。 glXMakeContextCurrent和 wglMakeContextCurrent将接受 drawables/HDC 的 Nil 参数。因此,您可以对帧缓冲区对象和所有其他内容执行 OpenGL 操作,唯一需要注意的是,没有主要的默认帧缓冲区。
随意使用这些代码片段来创建帮助器上下文。
#include "wglu_context.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/wglext.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
static char const *wgl_create_context_attribs_name = "wglCreateContextAttribsARB";
static
int wglu_get_proc_address(char const *name, PROC *pproc)
{
int rc= 0;
*pproc = wglGetProcAddress(name);
fprintf(stderr, "%s: %p\n", name, (void*)*pproc );
if( !(*pproc) ){
rc= GetLastError();
fprintf(stderr,
"error wglGetProcAddress('%s'): 0x%x\n",
name, rc);
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
/* -----------------------------------------------------------------------
* Create a OpenGL context of desired version and share it */
int wglu_create_context_with_sharing(
int major, int minor, int profile,
HDC surface,
HGLRC share_context,
HGLRC *out_context )
{
int rc= 0;
int attribs[8] = {0};
size_t i_attrib = 0;
HGLRC context = 0;
HDC const save_surface = wglGetCurrentDC();
HGLRC const save_context = wglGetCurrentContext();
if( save_surface != surface
|| save_context != share_context
){
wglMakeCurrent(surface, share_context);
}
PFNWGLCREATECONTEXTATTRIBSARBPROC wgl_create_context_attribs;
if( (rc= wglu_get_proc_address(
wgl_create_context_attribs_name,
(PROC*)&wgl_create_context_attribs))
){
goto fail;
}
if( major ){
attribs[i_attrib++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attribs[i_attrib++] = major;
}
if( minor ){
attribs[i_attrib++] = WGL_CONTEXT_MINOR_VERSION_ARB;
attribs[i_attrib++] = minor;
}
if( profile ){
attribs[i_attrib++] = WGL_CONTEXT_PROFILE_MASK_ARB;
attribs[i_attrib++] = profile;
}
attribs[i_attrib] = attribs[i_attrib+1] = 0;
context = wgl_create_context_attribs(surface, *share_context, attribs);
if( !context ){
rc= GetLastError();
fprintf(stderr,
"error %s(surface=0x%x, share_context=0x%x, attribs=0x%p): %x\n",
wgl_create_context_attribs_name,
(uintptr_t)surface, (uintptr_t)share_context,
attribs,
rc );
goto fail;
}
if( !(wglMakeCurrent(surface, context)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(surface=0x%x, contest=0x%x): 0x%x\n",
"wglMakeCurrent",
(uintptr_t)surface, (uintptr_t)context,
rc );
goto fail;
}
assert( context == wglGetCurrentContext() );
fprintf(stderr,
"GL_VENDOR = %s\n"
"GL_RENDERER = %s\n"
"GL_VERSION = %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION) );
if( !(wglMakeCurrent(NULL, NULL)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(0, 0): 0x%x\n",
"wglMakeCurrent",
(uintptr_t)surface, (uintptr_t)context,
rc );
goto fail;
}
if( !(wglShareLists(context, share_context)) ){
rc= GetLastError();
fprintf(stderr,
"error %s(context=0x%x, share_context=0x%x): 0x%x\n",
"wglShareLists",
(uintptr_t)context, (uintptr_t)share_context,
rc );
goto fail;
}
wglMakeCurrent(save_surface, save_context);
if( !rc ){
if( out_context ){ *out_context = context; }
} else {
if( context ){ wglDeleteContext(context); }
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
#include <GL/glxext.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <assert.h>
#include <errno.h>
#include <dlfcn.h>
static char const *glX_create_context_attribs_name = "glXCreateContextAttribsARB";
typedef void (*PROC)();
static
int glxu_get_proc_address(char const *name, PROC *pproc)
{
int rc= 0;
static PROC (*glX_get_proc_address)(char const*) = NULL;
if( !glX_get_proc_address ){
*(void**)(&glX_get_proc_address) = dlsym(RTLD_DEFAULT, "glXGetProcAddress");
}
if( !glX_get_proc_address ){
rc = -EFAULT;
} else {
*pproc = glX_get_proc_address(name);
fprintf(stderr, "%s: %p\n", name, (void*)*pproc );
if( !(*pproc) ){
rc= -ENOENT;
fprintf(stderr, "error glXGetProcAddress('%s'): so such function\n", name);
}
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
static
int glxu_get_fbconfig_for_xid(
Display *display,
GLXFBConfigID const id,
GLXFBConfig *out_fbconfig )
{
static GLXFBConfig* (*glX_get_fb_configs)(Display*,int,int*) = NULL;
static int (*glX_get_fb_config_attrib)(Display*,GLXFBConfig,int,int*) = NULL;
if( !glX_get_fb_configs ){
*(void**)(&glX_get_fb_configs) = dlsym(RTLD_DEFAULT, "glXGetFBConfigs");
}
if( !glX_get_fb_config_attrib ){
*(void**)(&glX_get_fb_config_attrib) = dlsym(RTLD_DEFAULT, "glXGetFBConfigAttrib");
}
int rc = 0;
int n_configs = 0;
/* we always assume to operate on screen 0, since hardly any X connection
* encountered these days actually operates on multiple screens. */
if( !glX_get_fb_configs || !glX_get_fb_config_attrib ){
rc = -EFAULT;
} else {
GLXFBConfig *const fbconfig = glX_get_fb_configs(display, 0, &n_configs);
for(int i=0; !rc && i < n_configs; ++i){
unsigned int qry_id;
rc= glX_get_fb_config_attrib(display, fbconfig[i], GLX_FBCONFIG_ID, &qry_id);
if( !rc && id == qry_id ){
*out_fbconfig = fbconfig[i];
break;
}
}
}
return rc;
}
Display *glxu_get_current_display(void)
{
static Display* (*glX_get_current_display)(void) = NULL;
if( !glX_get_current_display ){
*(void**)(&glX_get_current_display) = dlsym(RTLD_DEFAULT, "glXGetCurrentDisplay");
}
if( !glX_get_current_display ){
return NULL;
}
return glX_get_current_display();
}
GLXDrawable glxu_get_current_drawable(void)
{
static GLXDrawable (*glX_get_current_drawable)(void) = NULL;
if( !glX_get_current_drawable ){
*(void**)(&glX_get_current_drawable) = dlsym(RTLD_DEFAULT, "glXGetCurrentDrawable");
}
if( !glX_get_current_drawable ){
return 0;
}
return glX_get_current_drawable();
}
/* -----------------------------------------------------------------------
* Create a OpenGL context of desired version and share it */
int glxu_create_context_with_sharing(
int major, int minor, int profile,
Display *display,
GLXDrawable surface,
GLXContext share_context,
GLXContext *out_context )
{
int rc= 0;
int attribs[8] = {0};
size_t i_attrib = 0;
GLXContext context = 0;
unsigned int fbconfigxid = 0;
GLXFBConfig fbconfig = 0;
static GLXContext (*glX_get_current_context)(void) = NULL;
static void (*glX_query_drawable)(Display*,GLXDrawable,int,unsigned*) = NULL;
static Bool (*glX_make_current)(Display*,Drawable,GLXContext) = NULL;
static void (*glX_destroy_context)(Display*,GLXContext) = NULL;
if( !glX_get_current_context ){
*(void**)(&glX_get_current_context) = dlsym(RTLD_DEFAULT, "glXGetCurrentContext");
}
if( !glX_query_drawable ){
*(void**)(&glX_query_drawable) = dlsym(RTLD_DEFAULT, "glXQueryDrawable");
}
if( !glX_make_current ){
*(void**)(&glX_make_current) = dlsym(RTLD_DEFAULT, "glXMakeCurrent");
}
if( !glX_destroy_context ){
*(void**)(&glX_destroy_context) = dlsym(RTLD_DEFAULT, "glXDestroyContext");
}
if( !glX_get_current_context || !glX_query_drawable
|| !glX_make_current || !glX_destroy_context
){
return -EFAULT;
}
Display *const save_display = glxu_get_current_display();
GLXDrawable const save_surface = glxu_get_current_drawable();
GLXContext const save_context = glX_get_current_context();
if( !display ){ display = save_display; }
if( !surface ){ surface = save_surface; }
if( !share_context ){ share_context = save_context; }
if( save_display != display
|| save_surface != surface
|| save_context != share_context
){
fprintf(stderr, ".....\n");
if( !(glX_make_current(display, surface, share_context)) ){
rc = -1;
goto fail;
}
}
PFNGLXCREATECONTEXTATTRIBSARBPROC glX_create_context_attribs;
if( (rc= glxu_get_proc_address(
glX_create_context_attribs_name,
(PROC*)&glX_create_context_attribs))
){
rc = -2;
goto fail;
}
glX_query_drawable(display, surface, GLX_FBCONFIG_ID, &fbconfigxid);
glxu_get_fbconfig_for_xid(display, fbconfigxid, &fbconfig);
if( major ){
attribs[i_attrib++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[i_attrib++] = major;
}
if( minor ){
attribs[i_attrib++] = GLX_CONTEXT_MINOR_VERSION_ARB;
attribs[i_attrib++] = minor;
}
if( profile ){
attribs[i_attrib++] = GLX_CONTEXT_PROFILE_MASK_ARB;
attribs[i_attrib++] = profile;
}
attribs[i_attrib] = attribs[i_attrib+1] = 0;
context = glX_create_context_attribs(display, fbconfig, share_context, True, attribs);
if( !context ){
rc= -3;
fprintf(stderr,
"error %s(surface=0x%p, share_context=0x%p, attribs=0x%p): %x\n",
glX_create_context_attribs_name,
(void*)surface, (void*)share_context,
attribs,
rc );
goto fail;
}
if( !(glX_make_current(display, surface, context)) ){
rc= -4;
fprintf(stderr,
"error %s(surface=0x%p, contest=0x%p): 0x%x\n",
"wglMakeCurrent",
(void*)surface, (void*)context,
rc );
goto fail;
}
assert( context == glX_get_current_context() );
fprintf(stderr,
"GL_VENDOR = %s\n"
"GL_RENDERER = %s\n"
"GL_VERSION = %s\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION) );
fail:
glX_make_current(display, save_surface, save_context);
if( !rc ){
if( out_context ){ *out_context = context; }
} else {
if( context ){ glX_destroy_context(display, context); }
}
if( rc ){ fprintf(stderr, "%s: %d\n", __func__, rc); }
return rc;
}
Bool glxu_make_context_current(
Display* display,
GLXDrawable read, GLXDrawable draw,
GLXContext ctx )
{
static Bool (*glX_make_context_current)(Display*,Drawable,Drawable,GLXContext) = NULL;
if( !glX_make_context_current ){
*(void**)(&glX_make_context_current) = dlsym(RTLD_DEFAULT, "glXMakeContextCurrent");
}
if( !glX_make_context_current ){
return False;
}
return glX_make_context_current(display, read, draw, ctx);
}
关于c++ - 我如何创建一个线程安全的 QOffscreenSurface 供 OpenGl 使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65560109/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!