- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 OSX 上的单独线程中进行 OpenGL 渲染。我正在使用 SDL 创建窗口,但我想手动编写 OpenGL 上下文创建代码。有时它工作正常(它应该在红色区域中显示一个绿色方 block ),但有时它只显示白色。
如果我只在一个线程中运行(下面有一个#define 来打开和关闭它)一切正常。如果我插入一个停顿(一个 for 循环计数到 1000 万,另一个 #define 开关来控制它)它工作正常,这让我相信我有一个竞争条件,我需要阻塞渲染线程直到操作系统是完成它所做的一切。
不熟悉 Cocoa 或 Objective-C,我该怎么做?还是我的问题是别的?
代码如下:
#include </Library/Frameworks/SDL2.framework/Headers/SDL.h>
#include </Library/Frameworks/SDL2.framework/Headers/SDL_syswm.h>
#include <OpenGL/GL3.h>
#include <array>
#import <Cocoa/Cocoa.h>
#include <OpenGL/CGLTypes.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/CGLRenderers.h>
#include <thread>
namespace
{
float const PositionData[] =
{
-0.5f,-0.5f,0, 0,0,
0.5f,-0.5f,0, 0,0,
0.5f, 0.5f,0, 0,0,
0.5f, 0.5f,0, 0,0,
-0.5f, 0.5f,0, 0,0,
-0.5f,-0.5f,0, 0,0,
};
namespace buffer
{
enum type
{
VERTEX,
TRANSFORM,
MATERIAL,
MAX
};
}//namespace buffer
}//namespace
#define RENDER_THREAD
#define BLOCK_RENDER_THREAD
int main() {
Uint32 init_mode = SDL_INIT_VIDEO | SDL_INIT_TIMER;
#ifdef _DEBUG
init_mode |= SDL_INIT_NOPARACHUTE;
#endif
SDL_Init(init_mode);
Uint32 window_mode = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
SDL_Window* window;
if (NULL == (window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 500, 500, window_mode))) {
SDL_Quit();
return 1;
}
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if (!SDL_GetWindowWMInfo(window, &wmi) )
{
return 1;
}
std::atomic<bool> closing(false);
auto PollEventQueue = [&closing]() {
SDL_Event e;
while (SDL_PollEvent(&e)) {
switch (e.type)
{
case SDL_QUIT: {
closing = true;
} break;
default: {
} break;
}
}
};
NSWindow* native_window = wmi.info.cocoa.window;
auto RenderThreadMain = [native_window, &closing, PollEventQueue]() {
#ifdef BLOCK_RENDER_THREAD
for (int k = 0; k < 10000000; k++) {}
#endif
NSOpenGLContext* context;
@synchronized (native_window) {
NSOpenGLPixelFormat *pixel_format = nullptr;
NSOpenGLPixelFormatAttribute attributes[64] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAStencilSize, 8,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFANoRecovery,
0
};
NSOpenGLPixelFormatAttribute* the_end = std::find_if(std::begin(attributes), std::end(attributes), [](NSOpenGLPixelFormatAttribute attribute) {
return attribute == 0;
});
if (true) {
NSOpenGLPixelFormatAttribute multisample_attributes[] = {
NSOpenGLPFAMultisample,
NSOpenGLPFASampleBuffers, NSOpenGLPixelFormatAttribute(1),
NSOpenGLPFASamples, NSOpenGLPixelFormatAttribute(4),
0
};
// Copy it onto the attributes array
int k = 0;
while (multisample_attributes[k]) {
*(the_end++) = multisample_attributes[k++];
}
}
NSView* native_view = [native_window contentView];
NSRect native_rect = [native_view bounds];
pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
NSOpenGLView* gl_view = [[NSOpenGLView alloc] initWithFrame:native_rect pixelFormat:pixel_format];
[pixel_format release];
[gl_view setAutoresizingMask:
(NSViewHeightSizable|NSViewWidthSizable|NSViewMinXMargin|NSViewMaxXMargin|NSViewMinYMargin|NSViewMaxYMargin)
];
[native_view addSubview:gl_view];
context = [gl_view openGLContext];
GLint swap_interval = 1;
[context setValues:&swap_interval forParameter:NSOpenGLCPSwapInterval];
[context setView:[native_window contentView]];
[context makeCurrentContext];
}
std::array<GLuint, buffer::MAX> BufferName;
GLuint ProgramName;
GLuint VertexArrayName;
GLint UniformTransform;
GLint UniformMaterial;
const char* vertex_shader =
"#version 150 core\n"
"in vec3 Position;"
"in vec2 UV;"
"void main()"
"{"
" gl_Position = vec4(Position, 1.0);"
"}";
const GLint vertex_shader_length = (GLint)strlen(vertex_shader);
const char* fragment_shader =
"#version 150 core\n"
"out vec4 Color;"
"void main()"
"{"
" Color = vec4(0.0, 1.0, 0.0, 1.0);"
"}";
const GLint fragment_shader_length = (GLint)strlen(fragment_shader);
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource((GLuint)fragment_shader_id, 1, &fragment_shader, &fragment_shader_length);
glCompileShader((GLuint)fragment_shader_id);
int shader_compiled;
glGetShaderiv((GLuint)fragment_shader_id, GL_COMPILE_STATUS, &shader_compiled);
if (shader_compiled != GL_TRUE) {
int log_length = 0;
char log[1024];
glGetShaderInfoLog((GLuint)fragment_shader_id, 1024, &log_length, log);
printf("%s", log);
return 1; // TODO: Error
}
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource((GLuint)vertex_shader_id, 1, &vertex_shader, &vertex_shader_length);
glCompileShader((GLuint)vertex_shader_id);
glGetShaderiv((GLuint)vertex_shader_id, GL_COMPILE_STATUS, &shader_compiled);
if (shader_compiled != GL_TRUE) {
int log_length = 0;
char log[1024];
glGetShaderInfoLog((GLuint)vertex_shader_id, 1024, &log_length, log);
printf("%s", log);
return 1; // TODO: Error
}
ProgramName = glCreateProgram();
glAttachShader(ProgramName, fragment_shader_id);
glAttachShader(ProgramName, vertex_shader_id);
glBindAttribLocation(ProgramName, 0, "Position");
glLinkProgram(ProgramName);
glGenBuffers(buffer::MAX, &BufferName[0]);
glBindBuffer(GL_ARRAY_BUFFER, BufferName[buffer::VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(PositionData), PositionData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &VertexArrayName);
glBindVertexArray(VertexArrayName);
glBindBuffer(GL_ARRAY_BUFFER, BufferName[buffer::VERTEX]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (const GLvoid *)(3*sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(4);
glBindVertexArray(0);
while (!closing) {
#ifndef RENDER_THREAD
PollEventQueue();
#endif
glClearColor(1, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(ProgramName);
glBindVertexArray(VertexArrayName);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 2);
[context flushBuffer];
[context update];
}
return 0;
};
#ifdef RENDER_THREAD
std::thread render_thread = std::thread(RenderThreadMain);
while (!closing) {
PollEventQueue();
}
render_thread.join();
#else
RenderThreadMain();
#endif
return 0;
}
编译:
clang++ test.mm -framework OpenGL -framework Cocoa -framework SDL2 -F/Library/Frameworks -std=c++14 -g
最佳答案
首先,您应该熟悉 Apple 的 Thread Safety Summary对于 Cocoa(尤其是 AppKit)。在那里,您将了解到您不应该从辅助线程操纵 View 层次结构。特别是,对 -addSubview:
的调用很糟糕。 (请注意,那里描述的有关从后台线程绘图的限制仅适用于传统绘图。OpenGL 不要求您将焦点锁定在 View 上。)
使用 @synchronized(native_window)
并不像您想象的那样。它仅与在同一对象上显式使用 @synchronized()
的其他代码同步。它通常不与仅在该窗口上使用或操作的任何内容同步。我没有理由相信 Cocoa 中的任何东西都会在它的窗口上执行 @synchronized()
,所以你什么都没有同步。
由于窗口和上下文的设置是一次性工作,因此它可能应该在生成辅助线程之前在主线程上完成。
其次,您正在创建一个 NSOpenGLView
并从中获取上下文,但随后您要告诉上下文将其自身与不同的 View (窗口的 contentView
).你为什么要那样做? NSOpenGLView
拥有该上下文,它可能应该与该 View 保持关联。
最后,您使用的自动调整大小蒙版看起来很奇怪。由于您允许一切都变得灵活,因此 GL View 将不会与窗口的内容 View 保持同步。它会增长和收缩得更慢,它周围的边缘会像它一样获得和失去松弛。我猜你只是想要 NSViewHeightSizable|NSViewWidthSizable
以便 View 一起调整大小并且边距保持为 0。
关于c++ - OSX OpenGL 设置代码中的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41316289/
我带着为 OSX 编写 PAM 模块的永无休止的传奇再次回来了。我已经写好了模块。它在使用 ssh 或启动新的终端窗口或 su 时有效。我真正真正想要的只是 ssh 和登录窗口。 我的 PAM 模块在
我们有一个类似于Soundflower的虚拟音频设备驱动程序。该虚拟设备将在声音系统首选项中列出。每当我们的设备在系统偏好设置中被选择时,它就会阻止空闲 sleep 。如果我们将选择切换为默认输出设备
我带着为 OSX 编写 PAM 模块的永无止境的传奇又回来了。我已经编写了模块。它在使用 ssh 或启动新的终端窗口或 su 时有效。我真的、真的、真的想要的只是 ssh 和登录窗口。 我的 PAM
我想在 osx lion 上安装 pyaudio,但我无法做到。每次我尝试使用 pkg 时,它都不会安装任何东西。当我尝试使用 pip 安装它时,出现以下错误(以及许多其他行): lipo: can'
我使用 Java 进行开发已有很长时间了,但直到最近才从 Windows 切换到 OSX。在 Windows 中,我发现一切都足够简单易懂。我可以将 JDK 安装到一个选择的位置,其中还包括一个 JR
运行 Mac OSX 10.7.5 我想在 USB3 外部硬盘上启用 NTFS 并需要 UUID 来执行此操作( http://ntfsonmac.com ),但 diskutil 拒绝给我 UUID
我正在尝试为 Finder 创建服务,但我的应用程序不需要有 UI。好吧,我只需要一个 UI 来请求用户提供更多信息,我的应用程序有时可能需要这些信息。 但是应用程序应该在没有任何 UI 且 Dock
我正在尝试在我的 mac 上使用本地服务器,但它似乎忽略了/etc/hosts 文件中的 localhost 设置。找到了几个页面,其中解决方案是重新安装,并将 localhost 放在/etc/ho
这是一个 OSX 链接器问题。我不认为 OSX(BSD 或 Mach 层)在乎零页有多大,或者它是否真的存在。我认为这是一个工具的事情。但这是我的意见,这就是我问的原因。 -pagezero_size
我正在构建一个将在 iOS/OSX 应用中使用的模块。 客户坚持认为该模块可以在 iOS 和 OSX 上运行。 我需要检查我在 iOS 和 OSX 上使用 UIDevice 时使用的系统版本 FTWD
我尝试在 OSX 10.8.2 中使用 gnuplot,并看到 x11 是不明确或未知的终端类型。一些研究表明 x11 不受支持,我下载了 XQartz,但我仍然收到相同的错误消息。 我使用 expo
我从官方网站下载了 PostgreSQL 并运行了 .dmg 安装程序。之后我下载了 pgadmin3,我确实能够连接到数据库。 当我运行“psql”时,出现以下错误: psql: could not
自从升级到 OSX Catalina 以来,我一直遇到 UnsatisfiedLinkErrors 问题,尝试在 java 下运行 JNI 包装的库,其中包含多个 native 库引用,这些引用在早期
在 OSX 10.6 上使用 make 构建 C++ 项目时,我确定预处理器定义 __LP64__ 似乎始终自动由编译器(即,它没有在任何头文件中定义)(参见 Where is __LP64__ de
我正在尝试将我的 iOS 应用程序移植到 Mac OS X SDK,并且发现我收到以下错误消息:'Collection' redeclared as a different kind of symbo
我一直在 OSX 10.14 中成功使用我的代码生成 Metal 纹理: let textureLoaderOptions = [MTKTextureLoader.Option.origin : MT
我对编码有些陌生,想用 MySQL 后端启动我的第一个 Django 应用程序。我已经在我的 Windows 机器上使用这个设置将近一年了,但它是一个继承的代码库——不幸的是,我从未尝试过从头开始构建
我正在迁移到一台新计算机,同时从雪豹迁移到狮子。 phpunit 似乎没有进行迁移,所以我重新安装了它。然而,pear 的标准安装似乎不适用于我的 php 家庭brew 安装。这是错误: phpuni
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 已关闭 7 年前。 Improve
我在 OSX10.9 上为我的应用程序构建了一个 Java 7 bundle ,一切看起来都很好,但是当我在 OSX 10.7 上尝试它时,它在启动时崩溃,它已经在 10.7.3 和 10.7.5 上
我是一名优秀的程序员,十分优秀!