Open dmitrykolesnikovich opened 1 year ago
I think this is because I don't specify the version when creating the context, so the opengl version is below 3.2.
Try to print the version of the current context with the following lines:
glGetInteger(GL_MAJOR_VERSION)
glGetInteger(GL_MINOR_VERSION)
Also, try to change OpenGL profile to core (or compatibility)
I added printing versions inside LWJGLExecutor.initGLFunctions like so
println("major version: ${GL11.glGetInteger(GL30.GL_MAJOR_VERSION)}")
println("minor version: ${GL11.glGetInteger(GL30.GL_MINOR_VERSION)}")
and it printed me
major version: 4
minor version: 6
When I create 4.6 gl context like this
JNIEXPORT jlongArray JNICALL Java_com_huskerdev_ojgl_platforms_WinGLPlatform_nCreateContext(JNIEnv* env, jobject, jboolean isCore, jlong shareRc) {
checkBasicFunctions();
GLint context_attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 6,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
HGLRC rc;
if (!(rc = wglCreateContextAttribsARB(dc, (HGLRC)shareRc, context_attributes)))
std::cout << "Failed to create context (WGL)" << std::endl;
jlong array[2] = { (jlong)rc, (jlong)dc };
return createLongArray(env, 2, array);
}
then creation of texture does not work anymore (returns null
because this returns false
). I believe solving this should help with RenderDoc eventually because other people fixed their stuff this way.
Funny thing if you comment out explicit declaration of GL version in context_attributes
then everything will work properly as expected (BTW does not matter what GL version is explicitly requested 3.3, 4.6, etc)
JNIEXPORT jlongArray JNICALL Java_com_huskerdev_ojgl_platforms_WinGLPlatform_nCreateContext(JNIEnv* env, jobject, jboolean isCore, jlong shareRc) {
checkBasicFunctions();
GLint context_attributes[] = {
// WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
// WGL_CONTEXT_MINOR_VERSION_ARB, 6,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
HGLRC rc;
if (!(rc = wglCreateContextAttribsARB(dc, (HGLRC)shareRc, context_attributes)))
std::cout << "Failed to create context (WGL)" << std::endl;
jlong array[2] = { (jlong)rc, (jlong)dc };
return createLongArray(env, 2, array);
}
So I created branch with detailed description of how to reproduce RenderDoc issue on any machine with RenderDoc installed. Maybe this will motivate you to try it yourself. (JDK 18 needed)
Sorry, but I won't be able to test anything as I only have a phone right now. And it will be like this for another 4 months.
JavaFX creates empty texture with core profile in your case because of the different OpenGL context versions. Try to set d3d pipeline at the beginning of JavaFX app.
thanks for the suggestion, hope you are doing good
Hello,
I am also attempting to get Renderdoc to attach to my openglfx application. I see you've noted a fix for this issue above
Funny thing if you comment out explicit declaration of GL version in
context_attributes
then everything will work properly as expected (BTW does not matter what GL version is explicitly requested 3.3, 4.6, etc)JNIEXPORT jlongArray JNICALL Java_com_huskerdev_ojgl_platforms_WinGLPlatform_nCreateContext(JNIEnv* env, jobject, jboolean isCore, jlong shareRc) { checkBasicFunctions(); GLint context_attributes[] = { // WGL_CONTEXT_MAJOR_VERSION_ARB, 4, // WGL_CONTEXT_MINOR_VERSION_ARB, 6, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0 }; HGLRC rc; if (!(rc = wglCreateContextAttribsARB(dc, (HGLRC)shareRc, context_attributes))) std::cout << "Failed to create context (WGL)" << std::endl; jlong array[2] = { (jlong)rc, (jlong)dc }; return createLongArray(env, 2, array); }
but I do not understand how someone would apply that fix. It looks like c++ which I understand, but it seems as though you used this code and saw its effect. How could I go about using this as well? or how can i get a version of this codebase with that fix applied?
I see the .h files for win_utils.h and wgl.h and I see the line
@JvmStatic private external fun nCreateContext(isCore: Boolean, shareWith: Long): LongArray in WinGLPlatform.kt
I can see that it is calling into
win_utils_x64.dll so i suppose i need to add this function to win_utils.h then rebuild the dll. Which i did, but i fell short at linking it correctly into the WinUtils.kt functions
I am unclear on a few things. Perhaps due to my lack of familiarity with Kotlin and jni.
would you be willing to share the version of this code that includes this workaround for renderdoc?
As I wrote earlier, now I have nothing better than just a smartphone. So I can make any changes in the code only in the summer
I literally rebuild native ptoject https://github.com/husker-dev/offscreen-jgl
And then replaced .dll file with new one here https://github.com/husker-dev/openglfx/tree/master/core/src/main/resources/com/huskerdev/openglfx/natives
Kotlin approach to jni is simple external keyword that looks for implementation inside .dll packed inside JAR as resource.
Thank you @dmitrykolesnikovich !
Funny thing if you comment out explicit declaration of GL version in
context_attributes
then everything will work properly as expected (BTW does not matter what GL version is explicitly requested 3.3, 4.6, etc)
@dmitrykolesnikovich when you said this, did you mean that renderdoc could attach and capture? That is what I took it to mean, but using the dlls you've referenced above I am still getting the context attributes error when the fat jar from your branch project is run through RenderDoc.
what purpose would rebuilding the ojgl project serve? it appears that its nCreateContext function already does not include the wgl version numbers in version 1.2's files. https://github.com/husker-dev/offscreen-jgl/blob/main/native/windows.cpp Am I perhaps looking at the wrong code?
Well there is no working solution at the moment, the purpose is to play around with native code to find not only that it does not work, but also that there are different ways how it does not work. At least something to generate ideas on how to actually make it to work.
Tldr. No reason to rebuild ojgl
Gotcha, I just misinterpreted. I will let you know if I figure anything out. For now I'm just reimplementing my project in C# with OpenTK to get the GFX debugging I need. Incredibly suboptimal, but I'm already familiar with the OpenTK abstraction.
You can try to replace GL2 with GL3 here https://github.com/husker-dev/openglfx/blob/master/jogl/src/main/kotlin/com/huskerdev/openglfx/jogl/JOGLFXCanvas.kt#L16
This is not based on any understanding, just yet another thing to try
var gl: GL3? = null
get() {
if(field == null)
field = GLDrawableFactoryImpl.getFactoryImpl(GLProfile.get(GLProfile.GL3)).createExternalGLContext().gl.gL3
return field
}
It seems to me that RenderDoc is trying to attach to OpenGL context created by JavaFX. It uses "old fashioned" way that doesn't include any version and type (core/compatibility) selection. So, your problem occurs. It looks like this:
// Window creation
hwnd = createDummyWindow(szAppName);
hdc = GetDC(hwnd);
// Getting context using window
hglrc = wglCreateContext(hdc);
But OpenGLFX uses its own context with a "new" creation way. It includes wglCreateContextAttribsARB
and other brand new OpenGL features.
So, I think the problem is just incorrect selected context in RenderDoc.
Since OpenGLFX creates an offscreen GL contexts to perform rendering, RenderDoc needs to get some signals to fetch this context. It can be done using this API https://renderdoc.org/docs/in_application_api.html
I will try to implement it in near future.
That will be very-very relevant for my work. I am not a c++ guy, so will rely on your solution as is.
Well, I've combined RenderDoc and OpenGLFX, but the examples doesn't shows up as they use old-fashioned OpenGL. There are also some issues with wgl_nv_dx_interop which is used with the D3D pipeline on Windows.
Whatever, it is already something...
Actually in my first post I have opengl connection established (see picture). I am not sure wheter this is relevant though :)
You have connected to JavaFX but not to GL instance from OpenGLFX
Understand.
After some testing, I think it would be better not to use the RenderDoc API, but just be able to output the rendering simultaneously to another window that RenderDoc can connect to.
For now I'm only implementing this for Windows as it's the easiest thing to do.
I solved problems in the RenderDoc implementation. Now I will close the issue as completed.
A new version will be released soon, may be in a few days, when I test it with Linux and MacOS.
If you think that the problem is not resolved, reopen this issue.
Sorry my ignorance but it's still None in the API
I built fat jar and than ran it from inside Renderdoc via java -jar example.jar
There is a combobox with a selection of subprocesses. One of them is a process with OpenGL
I do attach to the process but without API being recognized.
I can check in a week. I don't have access to my Windows device right now.
My simple setup to reproduce:
1) build fat jar ES-4.0.5.jar
via gradlew modules:lwjgl2:fatJarES
with brand new fatJarES
gradle task
task fatJarES(type: Jar) {
manifest {
attributes 'Main-Class': 'LWJGL2_ES2Kt'
}
archiveBaseName = 'ES'
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { sourceSets.examples.runtimeClasspath.filter { file -> file.exists() }.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
2) run lwjgl2.bat
from renderdoc
I solved problems in the RenderDoc implementation. Now I will close the issue as completed.
A new version will be released soon, may be in a few days, when I test it with Linux and MacOS.
If you think that the problem is not resolved, reopen this issue.
What was the workaround?
Do I just call RenderDoc.bind(canvas, KeyCode.F12);
as the Readme says when I create the canvas? Does RenderDoc still need to be bound to the process before this happens?
RenderDoc.bind(canvas)
doesn't work for some reason. I'll leave that until the next big release. For now you can use RenderDoc.startFrameCapture()
and RenderDoc.startFrameCapture()
for segments that you want to capture.
gotcha. That explains a little bit.
I am having some trouble using the render doc methods.
When I use the bind method I get the error about NVDXInterop and so instead I create my canvas with InteropType.Blit, but when I do this the glGetInteger(GL_FRAMEBUFFER_BINDING)
returns 0 instead of the 2 I typically see it start at. I grab your built in FBO id for adding color attachments in the way you helped me with here
Is it the case that changing the InteropType to Blit means that OpenGLFX no longer uses a FrameBuffer for the render? I would have though that even if it uses a blit operation to transfer the image that it would still render in the same way onto a framebuffer...
But if the Bind command is broken anyways that's not my issue.
Do I still need to use InteropType.Blit with the RenderDoc.StartFrameCapture
method?
Without using InteropType.Blit... I have attempted to inject RenderDoc before creating my canvas and I see
then i let my application continue and for a moment RenderDoc shows me
then the JVM crashes hs_err_pid52152.log
siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), reading address 0x0000000000000000
Current thread (0x00000200c589f9c0): JavaThread "QuantumRenderer-0" daemon [_thread_in_native, id=97872, stack(0x0000009e42000000,0x0000009e42100000) (1024K)]
Stack: [0x0000009e42000000,0x0000009e42100000], sp=0x0000009e420fdcd0, free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [renderdoc.dll+0x9e9e16]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j com.huskerdev.openglfx.internal.d3d9.NVDXInterop.wglDXLockObjectsNV(JJ)Z+0
j com.huskerdev.openglfx.internal.d3d9.NVDXInterop.access$wglDXLockObjectsNV(JJ)Z+2
j com.huskerdev.openglfx.internal.d3d9.NVDXInterop$Companion.wglDXLockObjectsNV(JJ)Z+2
j com.huskerdev.openglfx.internal.d3d9.NVDXInterop$Companion.access$wglDXLockObjectsNV(Lcom/huskerdev/openglfx/internal/d3d9/NVDXInterop$Companion;JJ)Z+3
j com.huskerdev.openglfx.internal.d3d9.NVDXInterop$NVDXObject.lock()Z+14
j com.huskerdev.openglfx.internal.canvas.NVDXInteropCanvasImpl.renderContent(Lcom/sun/prism/Graphics;)V+248
j com.sun.javafx.sg.prism.NGNode.doRender(Lcom/sun/prism/Graphics;)V+330
j com.sun.javafx.sg.prism.NGNode.render(Lcom/sun/prism/Graphics;)V+35
j com.sun.javafx.sg.prism.NGGroup.renderContent(Lcom/sun/prism/Graphics;)V+151
j com.sun.javafx.sg.prism.NGRegion.renderContent(Lcom/sun/prism/Graphics;)V+111
...
@yetyman
The reason why InteropType.Blit
returns 0 framebuffer is because the glblitframebuffer
function is used to transfer the image from opengl to javafx, which does not require additional buffers.
And again, 0 is normal - it is the index of the very first buffer in the opengl life cycle.
Without InteropType.Blit
, NVDXInterop
is used, which requires the creation of a some “transit” framebuffers to send the image.
Openglfx does this, and gives you some other buffer to use.
You don't have to worry about the framebuffer index that openglfx generates.
For some reason renderdoc doesn't want to work with NVDXInterop. I do not know why. This is the reason of crash
With InteropType.Blit on, I get an error binding the render buffer to Color_Attachment_1: Invalid Operation(1282)
My command is
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, myRenderBufferID);
researching... https://registry.khronos.org/OpenGL-Refpages/es2.0/xhtml/glFramebufferRenderbuffer.xml it looks like color attachments can't be added to the default frame buffer, so in order to debug i think i will need to make my own intermediate framebuffer to render onto then copy its data to the default frame buffer
I'm using my own FrameBuffer now and its working! I can finally use RenderDoc! Thank you
GL context is created on Windows platform like so https://github.com/husker-dev/offscreen-jgl/blob/main/native/windows.cpp#L137 and optically
context_attributes
is here. But RenderDoc says "Context is created not viacreateContextAttribs
" (see screenshot). I never worked closely with native stuff myself. Maybe you can help me to make RenderDoc happy?