- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将 JCEF 提供的图像数据作为 ByteBuffer 复制到 OpenGL 纹理。当我使用适当的参数将提供的 ByteBuffer 传递给 glTexSubImage2D() 调用时,应用程序因 EXCEPTION_ACCESS_VIOLATION (0xc0000005) 崩溃。
我正在尝试做的事情:
JCEF 是 CEF(Chromium 嵌入式框架)的 Java 包装器,我目前正在使用离屏渲染模型(因为我想使用 opengl 在 3D 游戏中渲染浏览器)。
JCEF 通过 onPaint 方法从浏览器提供更新的屏幕数据,该方法包含脏矩形列表和包含更新的屏幕数据的 ByteBuffer。
我想使用 glTexSubImage2D 或类似工具将该 ByteBuffer 复制到 OpenGL 纹理上。
我已经确认传递给函数调用的所有值都是有效的,并且 JCEF 提供给我的缓冲区足够长。每次 OpenGL 库调用后调用 glGetError() 都会导致崩溃返回 0。
我的 opengl 库来自 LightWeight Java Game Library 3 (LWJGL3),我在所有其他代码中都使用了它。
在这里和其他各种论坛上对其他线程和问题的搜索都指出传递给 OpenGL glTexSubImage2D() 的 ByteBuffer 太短。我对此进行了两次和三次检查,但情况并非如此。 (据我对 OpenGL 的理解及其对数据格式和类型的解释告诉我。)
首先是一些基础类(class)。该代码是渲染引擎的一部分,因此我只会包含我认为相关的内容,但如果需要,我很乐意附加更多内容。
第一个类是 PreloadedTexture 类。这表示纹理不是直接来自文件,而是以某种方式修改或生成的。它是我的 OpenGL Texture2D 包装器。
package com.base.shader;
import java.nio.ByteBuffer;
import static org.lwjgl.opengl.GL45.*;
public class PreloadedTexture {
int width;//The width of the texture in pixels
int height;//The height of the texture in pixels
int handle;//The OpenGL handle for the texture. This is used to reference this texture in other OpenGL calls
/*
This constructor creates a blank texture with the dimensions specified.
*/
public PreloadedTexture(int width, int height) {
super(Math.random() + "");
this.width = width;
this.height = height;
this.handle = glGenTextures();
glBindTexture(GL_TEXTURE_2D, handle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
/*EDIT: This method was renamed and had the internals changed to not bind the texture to a uniform sampler as mentioned in my comment below. It now just does a call to glBindTexture() as the uniform binding would occasionally return errors.
*/
public void bind(){
glBindTexture(GL_TEXTURE_2D, handle);
}
}
BrowserWindow 类是大部分操作发生的地方,但我已经删除了与此问题无关的所有内容。
package com.base.game;
import com.base.shader.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.awt.*;
import java.util.concurrent.LinkedTransferQueue;
import static org.lwjgl.opengl.GL46.*;
public class BrowserWindow {
private PreloadedTexture texture;//The texture that should be copied to.
private ByteBuffer imgData;//The BytBuffer provided by CEF with the updated screen data.
private LinkedTransferQueue<Rectangle> dirtyRects = new LinkedTransferQueue<>();//The list of dirty rects. The reasoning behind a LinkedTransferQueue is explained below.
int width;//The width of the browser view in pixels.
int height;//The height of the browser view in pixels.
/*
* Creates a browser window with the specified width and height. Initialises a ByteBuffer with image data to draw and a texture to draw to.
*/
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES);//This is later filled by the JCEF code but I have removed that as I know it works.
//The ByteBuffer is filled with bytes representing the screen data in BGRA format. Each Byte is a separate component of a pixel. The pixels are grouped together.
//This results in a structure like so: [B,G,R,A,B,G,R,A,etc.] I have maually checked that this data looks valid by going through portions of it and seeing understandable variances in the values.
texture = new PreloadedTexture(width, height); // An instance of the above PreloadedTexture class. The final destination for the imgData above.
}
//Called when the engine whats to render a frame. This should update the texture of the browser and then render the mesh with this texture. The actual mesh rendering code is ommited because again I know that works and it is not where the issue lies.
public void render(ShaderProgram shaderProgram, Camera camera) {
synchronized (imgData) {
//This block is to allow communication with the CEF thread.
//CEF runs the browser in a seperate thread and the onPaint method is called from there.
//OpenGL is not initialised in that thread however so I have used a LinkedTransferQueue<Rectangle> to transfer the dirty portions that need to be redrawn and the updated ByteBuffer is transferred byt directly setting it on the class.
//Again the actual code that does this has been ommitted as I know by checking the values manually that the data that is transfered is correct.
if (dirtyRects.size() > 0) {
//This just checks that there are dirty portions to update otherwise the call would waste both CPU and GPU time.
ArrayList<Rectangle> rects = new ArrayList<>();
//This provides a list to drop the Rectangles into for ease of access. These rectangles aren;t used at the moment but their implementation can be seen in the below commented out code.
dirtyRects.drainTo(rects);
imgData.rewind();
//This ensures that the imgData buffer is at the beggining.
texture.bind();
//Here I bind the texture to GL_TEXTURE_2D. The actual implementation is shown above in PreloadedTexture class.
System.out.println("Pre Render Error: " + glGetError());
//This checks to see if OpenGL was in an invalid state before and also clears the error buffer to ensure any errors reported from now on actually occur in this method.
System.out.println(glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) + ", " + glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT));
//This is a sanity check to ensure that the texture was initialised correctly in the PreloadedTexture constructor.
System.out.println(imgData.limit() + ", " + width * height * 4);
//This is another sanity check to ensure that the ByteBuffer is actually large enough. At the moment I have given it extra data to work with to see if it was the problem, hence the much larger limit of the ByteBuffer compared to the computed nescesary amount.
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
//These two calls reset the OpenGL state to ensure that rows and pixels aren't being skipped.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imgData);//This line results in the EXCEPTION_ACCESS_VIOLATION (0xc0000005)
System.out.println("Render Error: " + glGetError()); //This is a sanity check from before with another problem that I fixed.
//Below is the implementation that made use of the rectangles. It follows a similar pattern to the above code but only updates the specified rectangles.
// for (Rectangle rect : rects) {
// System.out.println(rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height);
// glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
// glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
// glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,imgData);
// }
}
imgData.notifyAll();//This notifies the CEF thread that the Rectangles and imgData objects are now free.
}
//Mesh rendering would happen here but again it has been omitted for conciseness this is not where the problem lies.
}
}
正如我在代码注释中提到的,我已仔细检查 CEF 中的数据是否采用有效格式。它遵循 4 字节重复 BGRA 值序列。 ByteBuffer 足够长,如调用 glTexSubImage2D() 之前的健全性检查所示;
抱歉代码量太大,但正如我之前所说,它是渲染引擎的一部分,并且大部分结构都受到这一事实的影响。
我希望调用 glTexSubImage2D() 将 ByteBuffer 数据复制到 OpenGL Texture2D 上,但是调用会导致 EXCEPTION_ACCESS_VIOLATION (0xc0000005)。 ByteBuffer 足够长,并且里面的数据格式有效。我还尝试将 GL_UNSIGNED_INT_8_8_8_8_REV 与 GL_UNSIGNED_INT_8_8_8_8 和 GL_UNSIGNED_BYTE 交换,但它们不会影响结果。查看日志时出现异常,因为它尝试访问地址 0x0000000000000010。
有谁知道什么可能导致此错误。我所有的研究都表明 ByteBuffer 太短了,但是,正如我所说的,我已经仔细检查了这一点。我对正在发生的事情的理解是否有缺陷或者是别的什么?
最佳答案
在查看错误日志并查看库源代码之后,我追踪到错误是如何分配 ByteBuffer 的。 OpenGL 库使用了内存偏移访问器(原因很明显),但获取偏移量的方法要求 ByteBuffer 是直接的。将 BrowserWindow 类更改为使用直接缓冲区已修复该错误。
下面列出了更新的部分,供遇到类似问题的其他人使用。
//This is the updated constructor from the BrowserWindow class
public BrowserWindow(int _w, int _h){
width = _w;
height = _h;
//imgData = ByteBuffer.allocate(width * height * 4 * Integer.BYTES); This is the old line that created a non-direct ByteBuffer.
imgData = ByteBuffer.allocateDirect(width * height * 4);//This is the new line. Note the allocateDirect() call and the removal of the extra space in the buffer in the form of Integer.BYTES.
texture = new PreloadedTexture(width, height);
}
关于java - 尽管确认传递的数据缓冲区足够长,但 glTexSubImage2D() 导致 EXCEPTION_ACCESS_VIOLATION (0xc0000005),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56872469/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我试图用这种形式简单地获取数字 28 integer+space+integer+integer+space+integer我试过这个正则表达式 \\s\\d\\d\\s 但我得到了两个数字11 和
最近一直在学习D语言。我一直对运行时感到困惑。 从我能收集到的关于它的信息中,(这不是很多)我知道它是一种有助于 D 的一些特性的运行时。像垃圾收集一样,它与您自己的程序一起运行。但是既然 D 是编译
想问一下这两个正则表达式有区别吗? \d\d\d 与 \d{3} 我已经在我的本地机器上使用 Java 和 Windows 操作系统对此进行了测试,两者都工作正常并且结果相同。但是,当在 linux
我正在学习 Go,而且我坚持使用 Go 之旅(exercise-stringer.go:https://tour.golang.org/methods/7)。 这是一些代码: type IPAddr
我在Java正则表达式中发现了一段令我困惑的代码: Pattern.compile( "J.*\\d[0-35-9]-\\d\\d-\\d\\d" ); 要编译的字符串是: String string
我在 ruby 代码上偶然发现了这个。我知道\d{4})\/(\d\d)\/(\d\d)\/(.*)/是什么意思,但是\1-\2-\3-\4 是什么意思? 最佳答案 \1-\2-\3-\4 是 b
我一直在努力解决这个问题,这让我很恼火。我了解 D 运行时库。它是什么,它做什么。我也明白你可以在没有它的情况下编译 D 应用程序。就像 XoMB 所做的那样。好吧,XoMB 定义了自己的运行时,但是
我有两个列表列表,子列表代表路径。我想找到所有路径。 List> pathList1 List> pathList2 当然是天真的解决方案: List> result = new ArrayList>
我需要使用 Regex 格式化一个字符串,该字符串包含数字、字母 a-z 和 A-Z,同时还包含破折号和空格。 从用户输入我有02-219 8 53 24 输出应该是022 198 53 24 我正在
目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。 import std.datetime : benc
tl;dr:你好吗perfect forwarding在 D? 该链接有一个很好的解释,但例如,假设我有这个方法: void foo(T)(in int a, out int b, ref int c
有什么方法可以在 D 中使用abstract auto 函数吗? 如果我声明一个类如下: class MyClass { abstract auto foo(); } 我收到以下错误: mai
有没有人为内存中重叠的数组切片实现交集?算法在没有重叠时返回 []。 当 pretty-print (使用重叠缩进)内存中重叠的数组切片时,我想要这个。 最佳答案 如果您确定它们是数组,那么只需取 p
我已经开始学习 D,但我在使用 Andrei Alexandrescu 所著的 The D Programming Language 一书中提供的示例时遇到了一些麻烦。由于 int 和 ulong 类
如何创建一个不可变的类? 我的目标是创建一个实例始终不可变的类。现在我只是用不可变的方法和构造函数创建了一个“可变”类。我将其称为 mData,m 表示可变。然后我创建一个别名 alias immut
不久前我买了《The D Programming Language》。好书,很有教育意义。但是,我在尝试编译书中列出的语言功能时遇到了麻烦:扩展函数。 在这本书中,Andrei 写了任何可以像这样调用
我在 D http://www.digitalmars.com/d/2.0/lazy-evaluation.html 中找到了函数参数的惰性求值示例 我想知道如何在 D 中实现可能的无限数据结构,就像
这个问题在这里已经有了答案: 12 年前关闭。 Possible Duplicate: Could anyone explain these undefined behaviors (i = i++
当前是否可以跨模块扫描/查询/迭代具有某些属性的所有函数(或类)? 例如: source/packageA/something.d: @sillyWalk(10) void doSomething()
我是一名优秀的程序员,十分优秀!