Программа Java с LWJGL вызывает многочисленные проблемы с Metal на macOSJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Программа Java с LWJGL вызывает многочисленные проблемы с Metal на macOS

Сообщение Anonymous »

Я написал простое, в основном работающее приложение OpenGL на Java (версия 21), используя LWJGL на своем MacBook. Сама программа работает нормально, но были многочисленные сбои, связанные с Metal или управлением памятью. Похоже, что Apple эмулирует OpenGL с помощью Metal, что объясняет, почему LWJGL, являющийся привязкой для OpenGL, Vulkan и связанных с ними библиотек, вызывает ошибки, связанные с Metal. Вот несколько примеров того, что я видел:

Код: Выделить всё

-[IOGPUMetalCommandBuffer validate]:214: failed assertion 'commit command buffer with uncommitted encoder'
Эта ошибка произошла, когда я впервые добился корректной работы текстур изображения с настраиваемыми параметрами. Текстура загружается, отображается и применяет любую конфигурацию, предоставленную объекту Текстура. Однако если программа будет оставаться открытой слишком долго, это утверждение не будет выполнено.

Код: Выделить всё

-[AGXG13XFamilyCommandBuffer renderCommandEncoderWithDescriptor:]:964: failed assertion 'A command encoder is already encoding to this command buffer'
После повторного запуска программы с минимальными изменениями (я даже не уверен, что я вообще что-то изменил) она снова вылетела, на этот раз с вышеуказанным сообщением об ошибке. Каким-то образом код без изменений или с очень небольшим количеством изменений, работающий с теми же доступными ему ресурсами, что и раньше, вызвал другое утверждение.

Код: Выделить всё

/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home/bin/java -XstartOnFirstThread -javaagent:[idea runtime and lwjgl stuff from my .m2 dir] net.bunsoft.bunworks.examples.Main
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000133f158d8, pid=21546, tid=51971
#
# JRE version: Java(TM) SE Runtime Environment (21.0.2+13) (build 21.0.2+13-LTS-58)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (21.0.2+13-LTS-58, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# C  [AppleMetalOpenGLRenderer+0x158d8]  std::__1::pair std::__1::__hash_table::__emplace_unique_key_args(GLRResource* const&, GLRResource*&)+0x5c
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/audrey/Documents/Code/jBunworks/hs_err_pid21546.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

Process finished with exit code 134 (interrupted by signal 6:SIGABRT)
Этот вопрос мучил меня с тех пор, как я впервые открыл окно с GLFW. Это происходит каждый раз, когда я изменяю размер окна. Не знаю почему, тем более, что развертывание окна в полноэкранном режиме не приводит к вылету. Иногда после того, как произошел этот сбой, перезапуск программы приводит к ее немедленному сбою.
Это метод, который я использую для создания текстуры OpenGL:

Код: Выделить всё

    protected void generate() {
glBindTexture(GL_TEXTURE_2D, id);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
}
Идентификатор генерируется при создании объекта текстуры. Он создается заново каждый раз, когда загружается новое изображение, изменяется режим переноса или режим фильтра.
Это все соответствующие классы (

Код: Выделить всё

GraphicsDeviceКод 
и RenderTarget удален для краткости):

Код: Выделить всё

package net.bunsoft.bunworks.render;

import net.bunsoft.bunworks.core.ResourceHelper;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.MemoryStack;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import static org.lwjgl.opengl.GL13C.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13C.glActiveTexture;
import static org.lwjgl.opengl.GL30C.glGenerateMipmap;
import static org.lwjgl.stb.STBImage.*;
import static org.lwjgl.opengl.GL11C.*;

public class Texture {
protected int id;

protected ByteBuffer image;
protected int width;
protected int height;
protected int nChannels;

private int wrapMode;
private int minFilter;
private int magFilter;

public Texture() {
id = glGenTextures();
wrapMode = GL_REPEAT;
minFilter = GL_LINEAR_MIPMAP_LINEAR;
magFilter = GL_LINEAR;

generate();
}

public Texture(int width, int height, int nChannels) {
this();

this.width = width;
this.height = height;
this.nChannels = nChannels;

image = ByteBuffer.allocate(width * height * nChannels);
generate();
}

public Texture(String path) {
this();
loadImage(path);
}

public void loadImage(String path) {
byte[] bytes = ResourceHelper.loadBytes(path);
ByteBuffer buf = MemoryUtil.memAlloc(bytes.length);
buf.put(bytes).flip();

try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer pw = stack.mallocInt(1);
IntBuffer ph = stack.mallocInt(1);
IntBuffer pc = stack.mallocInt(1);

image = stbi_load_from_memory(buf, pw, ph, pc, 0);
width = pw.get();
height = ph.get();
nChannels = pc.get();

if (image == null) {
System.err.println("Failed to load texture image "  + path);
}
} finally {
MemoryUtil.memFree(buf);
}

generate();
}

public void use(int texUnit) {
glActiveTexture(GL_TEXTURE0 + texUnit);
glBindTexture(GL_TEXTURE_2D, id);
}

public void resize(int w, int h) {
width = w;
height = h;

image = ByteBuffer.allocate(width * height * nChannels);
generate();
}

public int getWrapMode() {
return wrapMode;
}

public void setWrapMode(int wrapMode) {
this.wrapMode = wrapMode;
generate();
}

public int getMinFilter() {
return minFilter;
}

public int getMagFilter() {
return magFilter;
}

public void setFilter(int min, int mag) {
minFilter = min;
magFilter = mag;
generate();
}

protected void generate() {
glBindTexture(GL_TEXTURE_2D, id);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
}
}

Код: Выделить всё

package net.bunsoft.bunworks.render;

import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.IntBuffer;

import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Window {
private int x;
private int y;
private int w;
private int h;
private String caption;

private long handle;

public Window(int x, int y, int w, int h, String caption) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.caption = caption;
}

public void init() {
GLFWErrorCallback.createPrint(System.err).set();

if (!glfwInit())
throw new IllegalStateException("Windowing system init failed!");

glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);

handle = glfwCreateWindow(w, h, caption, NULL, NULL);
if (handle == NULL)
throw new RuntimeException("Window creation failed!");

try (MemoryStack stack = MemoryStack.stackPush()) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1);  // int*

glfwGetWindowSize(handle, pWidth, pHeight);

GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
assert vidMode != null;

glfwSetWindowPos(
handle,
(vidMode.width() - pWidth.get(0)) / 2,
(vidMode.height() - pHeight.get(0)) / 2
);
}

glfwSetFramebufferSizeCallback(handle, this::onResize);

glfwMakeContextCurrent(handle);
glfwSwapInterval(1);

glfwShowWindow(handle);
}

public void handleEvents() {
glfwSwapBuffers(handle);
glfwPollEvents();
}

public void close() {
glfwFreeCallbacks(handle);
glfwDestroyWindow(handle);

glfwTerminate();
glfwSetErrorCallback(null).free();
}

public void makeContentCurrent() {
glfwMakeContextCurrent(handle);
GL.createCapabilities();
}

public boolean shouldClose() {
return glfwWindowShouldClose(handle);
}

protected void onResize(long l, int i, int i1) {
w = i;
h = i1;
//surface.resize(w, h);
}
}

Код: Выделить всё

package net.bunsoft.bunworks.core;

import net.bunsoft.bunworks.render.GraphicsDevice;
import net.bunsoft.bunworks.render.Window;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Game {
public static final double FRAMERATE = 300.0;
public static final double STEPRATE = 240.0;

//protected GraphicsDevice gfx;
protected Window window;

private boolean isRunning;
private int exitCode;

private long frameCounter;
private long stepCounter;
private double timer;

public Game() {
isRunning = false;
exitCode = 0;

window = new Window(100, 100, 640, 480, "Bunworks Game");
//gfx = new GraphicsDevice();
}

public void run() {
isRunning = true;
start();

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(this::step, 0, (long) (1000000 / STEPRATE), TimeUnit.MICROSECONDS);
executor.scheduleAtFixedRate(this::doDraw, 0, (long) (1000000 / FRAMERATE), TimeUnit.MICROSECONDS);

while (isRunning) {
window.handleEvents();
if (window.shouldClose())
exit(0);
}

executor.shutdown();
end();
}

public void exit(int exitCode) {
this.exitCode = exitCode;
isRunning = false;
}

public int getExitCode() {
return exitCode;
}

public long getFrameCounter() {
return frameCounter;
}

public long getStepCounter() {
return stepCounter;
}

public double getTimer() {
return timer;
}

protected void start() {
window.init();
window.makeContentCurrent();

//gfx.init();
}

protected void step() {
stepCounter++;
timer += 1 / STEPRATE;
}

private void doDraw() {
window.makeContentCurrent();

//gfx.drawStart();
draw();
//gfx.drawEnd();

frameCounter++;
}

protected void draw() {

}

protected void end() {
window.close();
}

}

Код: Выделить всё

package net.bunsoft.bunworks.render;

import static org.lwjgl.opengl.GL15C.*;
import static org.lwjgl.opengl.GL20C.*;
import static org.lwjgl.opengl.GL30C.*;

public class Mesh {
private int vbo;
private int vao;
private int ebo;

private Vertex[] vertices;
private float[] vertexData;
private int[] indices;

public Mesh() {
vbo = glGenBuffers();
vao = glGenVertexArrays();
ebo = glGenBuffers();

vertexData = new float[0];
indices = new int[0];
}

public Mesh(Vertex[] vertices,  int[] indices) {
this();

setVertices(vertices);
setIndices(indices);
}

public void setVertices(Vertex[] vertices) {
this.vertices = vertices;
this.vertexData = new float[vertices.length * Vertex.SIZE];

for (int i = 0; i < vertexData.length; i += Vertex.SIZE) {
Vertex vert = vertices[i / Vertex.SIZE];

vertexData[i] = (float) vert.x;
vertexData[i + 1] = (float) vert.y;
vertexData[i + 2] = (float) vert.z;
vertexData[i + 3] = 1.0f;
vertexData[i + 4] = (float) vert.r;
vertexData[i + 5] = (float) vert.g;
vertexData[i + 6] = (float) vert.b;
vertexData[i + 7] = (float) vert.a;
vertexData[i + 8] = (float) vert.u;
vertexData[i + 9] = (float) vert.v;
}

glBindVertexArray(vao);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);

int stride = Vertex.SIZE * Float.BYTES;
glVertexAttribPointer(0, 4, GL_FLOAT, false, stride, 0L);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, false, stride, 4L * Float.BYTES);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, false, stride, 8L * Float.BYTES);
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

public void setIndices(int[] indices) {
this.indices = indices;

glBindVertexArray(vao);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this.indices, GL_STATIC_DRAW);

glBindVertexArray(0);
}

public void draw() {
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
}

Код: Выделить всё

package net.bunsoft.bunworks.render;

import net.bunsoft.bunworks.core.Property;
import net.bunsoft.bunworks.core.Vec3;

import java.util.HashMap;
import java.util.List;

public class Material {
private ShaderProgram shader;
private HashMap

Подробнее здесь: [url]https://stackoverflow.com/questions/79803894/java-program-with-lwjgl-causes-numerous-issues-with-metal-on-macos[/url]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»