Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (806)
Games in Android Showcase (239)
games submitted by our members
Games in WIP (868)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 2 [3] 4 5 ... 7
  ignore  |  Print  
  Vulkan 1.0 Release  (Read 132765 times)
0 Members and 1 Guest are viewing this topic.
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #60 - Posted 2016-02-20 11:58:36 »

Hmm... this is a hard problem.
Let's stay with the facts:
- we need different functions for different contexts (instance, device)

Let's assume the following desired properties:
- we want for LWJGL users to call Vulkan functions easily with methods named after the Vulkan functions

How to provide context?
1. Like you said, with dispatching via object-orientation using implied this parameters for a given Vulkan instance and/or device (this would mean that it is not possible to call Vulkan methods anymore with static methods)
2. With adding an additional parameter to each (instance, [device])-sensitive method that takes the manually lookedup Vulkan function pointer (this can also be the low level on which the previously mentioned object-oriented layer can sit on top of)
3. With letting LWJGL's Vulkan methods keep track of the respective function pointer given the (instance, [device]) context as method parameters for each method invocation. This means, LWJGL would need to hold state/keep track of the current context (which function was invoked to create an instance/device, etc) in a thread-local manner and for each method invocation choose the correct Vulkan function pointer. Probably not a good idea.

Currently, I find none of the above three methods appealing at all. Smiley
If I had to choose, I would probably opt for 2. and if so definitely head to 1. as soon as possible with 2. providing the basis.
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #61 - Posted 2016-02-20 14:08:24 »

For all SWT fans, I added Vulkan support on Win32 for a SWT Canvas (much like SWT's GLCanvas for OpenGL support) to the lwjgl3-swt project.

Example code:
1  
2  
3  
4  
5  
6  
7  
8  
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
VKData data = new VKData(); // <- like GLData for OpenGL
data.instance = instance; // <- The VkInstance created outside with LWJGL 3
VKCanvas canvas = new VKCanvas(shell, SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE, data);
long surface = canvas.surface; // <- the VkSurfaceKHR to stuff into VkSwapchainCreateInfoKHR
shell.open();

This allows to embed Vulkan into your SWT/Eclipse application.
Offline Spasi
« Reply #62 - Posted 2016-02-20 14:19:15 »

The latest nightly build (3.0.0 #28) replaces memFree(StructBuffer) with StructBuffer.free() and adds "auto-size" support for struct members. Both are breaking changes.

Hmm... this is a hard problem.
...
Currently, I find none of the above three methods appealing at all. Smiley
If I had to choose, I would probably opt for 2. and if so definitely head to 1. as soon as possible with 2. providing the basis.

Lets explore some options with actual code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
// Global commands looked up with vkGetInstanceProcAddr(NULL, ...):
// vkEnumerateInstanceLayerProperties
// vkEnumerateInstanceExtensionProperties
// vkCreateInstance

// ..blahblah
VkInstanceCreateInfo ici = ...;
vkCreateInstance(ici, null, myInstance);

// Option 1: Create binding with explicit instance/device argument, use non-static methods
// Function pointer retrieved from "this".
VKCapabilities caps = new VKCapabilities(myInstance);
caps.VK10.MapMemory(...);
caps.EXTDebugReport.CreateDebugReportCallbackEXT(...);

// and/or
VK10 vk = caps.VK10; // or new VK10(myInstance)
vk.MapMemory(...);
EXTDebugReport debug = caps.EXTDebugReport; // or new EXTDebugReport(myInstance)
debug.CreateDebugReportCallbackEXT(...);

// Option 2: Create binding with explicit instance/device argument, use static methods
// Function pointer retrieved from an extra parameter.
VKCapabilities caps = new VKCapabilities(myInstance);
vkMapMemory(caps, ...);
CreateDebugReportCallbackEXT(caps, ...);

// or
VK10 vk = caps.VK10; // or new VK10(myInstance)
vkMapMemory(vk, ...);
EXTDebugReport debug = caps.EXTDebugReport; // or new EXTDebugReport(myInstance)
CreateDebugReportCallbackEXT(debug, ...);

// Option 3: LWJGL-style, assuming 99% of users will use different threads for different VkInstances/VkDevices.
// Function pointer retrieved from thread-local state, explicitly set by the user.
VKCapabilities caps = new VKCapabilities(myInstance);
VK.setCapabilities(caps); // in each thread

vkMapMemory(...);
CreateDebugReportCallbackEXT(...);

I'm between 2 and 3. I just don't know how well the assumption in 3 holds.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #63 - Posted 2016-02-20 14:31:28 »

Okay, I think I changed my mind. You are right, option 3 is LWJGL-style and now I am sooo absolutely in favor of option 3 with the instance hidden in thread-local context!
I think it looks really ugly and is error-prone as hell having to drag the VkInstance (in whatever form) with the method invocations.
But I also had something else in mind, with not storing the function pointers in thread-local, but looking it up based on the actual argument of the Vulkan method invocations, so that even if a user forgot to set the thread-local or used the wrong one, it would still work correctly. But LWJGL would have to do some lookup for each method invocation.
Offline Spasi
« Reply #64 - Posted 2016-02-20 15:18:30 »

But I also had something else in mind, with not storing the function pointers in thread-local, but looking it up based on the actual argument of the Vulkan method invocations, so that even if a user forgot to set the thread-local or used the wrong one, it would still work correctly. But LWJGL would have to do some lookup for each method invocation.

Yes, the lookup would be expensive. Another option would be to convert the 5 dispatchable handles from longs to objects:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
// ..blahblah
VkInstanceCreateInfo ici = ...;
PointerBuffer p = ...;

vkCreateInstance(ici, null, p);
VkInstance myInstance = new VkInstance(p.get(0)); // creates a VKCapabilities instance internally (using vkGetInstanceProcAddr)

vkEnumeratePhysicalDevices(myInstance, deviceCount, physicalDevices); // function pointer retrieved from myInstance.caps.VK10.EnumeratePhysicalDevices
VkPhysicalDevice pd = new VkPhysicalDevice(myInstance, physicalDevices.get(0)); // pd.caps == myInstance.caps

vkCreateDevice(pd, ..., p); // function pointer retrieved from pd.caps.VK10.CreateDevice
VkDevice dev = new VkDevice(p.get(0)); // dev.caps will be a new VKCapabilities instance created using vkGetDeviceProcAddr

// similarly, VkQueues and VkCommandBuffers will share the VKCapabilities instance of the device from which they are created

The LWJGL generator had support for object handles in the past, it'd be easy to restore that functionality and implement the above. Since there are only 5 dispatchable handles and they correspond to "heavyweight" objects that will not be frequently created/destroyed, I think this a viable solution.
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #65 - Posted 2016-02-20 16:40:59 »

Could you show how actual method invocations of Vulkan functions would look like, then?
Does this now impose an OO design to the solution?
Do methods have to be invoked on the respective VkInstance/VkPhysicalDevice/VkDevice... objects?

Also, one rather peculiar thing I just noticed: Looking up the instance-specific function 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR' using VK10.vkGetInstanceProcAddr() with a valid 'instance' returns 0L whereas looking it up with getFunctionAddress on the VK10.getLibrary() returns a valid function pointer...

I have to look up whether this is by the spec. This would mean that LWJGL have to try to lookup the instance/device-specific function address, and if that failed, use simply GetProcAddress.
Offline theagentd
« Reply #66 - Posted 2016-02-20 16:59:52 »

I would have 0 problems replacing all the Vulkan objects stored as long addresses with actual objects. The Vulkan spec does call them objects/structs/whatever after all. There's no point in returning the long addresses from the functions as well if all functions that used to use them now need the object instead; just create the object for us and return it. And you're right, Spasi; as long as the objects aren't frequently created or destroyed we won't even have a problem with garbage when doing this. My vote is for automatic object wrapping.

Myomyomyo.
Offline Spasi
« Reply #67 - Posted 2016-02-20 17:20:54 »

Could you show how actual method invocations of Vulkan functions would look like, then?
Does this now impose an OO design to the solution?
Do methods have to be invoked on the respective VkInstance/VkPhysicalDevice/VkDevice... objects?

Exactly like they are now, except that instead of passing (as the first parameter) a long dispatchable handle (they're always the first parameter), you pass an instance of a Java class (VkInstance, VkDevice, VkQueue, etc). Nothing else changes. There's no thread-local state and all methods are static.

Also, one rather peculiar thing I just noticed: Looking up the instance-specific function 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR' using VK10.vkGetInstanceProcAddr() with a valid 'instance' returns 0L whereas looking it up with getFunctionAddress on the VK10.getLibrary() returns a valid function pointer...

I have to look up whether this is by the spec. This would mean that LWJGL have to try to lookup the instance/device-specific function address, and if that failed, use simply GetProcAddress.

Don't worry about that, it's how OpenGL/CL/AL work too. It will be handled automatically on VKCapabilities creation.

I would have 0 problems replacing all the Vulkan objects stored as long addresses with actual objects. The Vulkan spec does call them objects/structs/whatever after all. There's no point in returning the long addresses from the functions as well if all functions that used to use them now need the object instead; just create the object for us and return it. And you're right, Spasi; as long as the objects aren't frequently created or destroyed we won't even have a problem with garbage when doing this. My vote is for automatic object wrapping.

Automatic wrapping is not possible, because all object creations go into output parameters and all Vulkan functions already have a return value (the error code).

As for replacing all handles, it doesn't make sense for non-dispatchable handles. They won't hold any other state and the frequency of creation/destruction of such handles would needlessly generate Java garbage. This is also why the OpenCL bindings in LWJGL 3 use primitive handles instead of the object handles we had in LWJGL 2.
Offline theagentd
« Reply #68 - Posted 2016-02-20 17:28:38 »

I would have 0 problems replacing all the Vulkan objects stored as long addresses with actual objects. The Vulkan spec does call them objects/structs/whatever after all. There's no point in returning the long addresses from the functions as well if all functions that used to use them now need the object instead; just create the object for us and return it. And you're right, Spasi; as long as the objects aren't frequently created or destroyed we won't even have a problem with garbage when doing this. My vote is for automatic object wrapping.

Automatic wrapping is not possible, because all object creations go into output parameters and all Vulkan functions already have a return value (the error code).

As for replacing all handles, it doesn't make sense for non-dispatchable handles. They won't hold any other state and the frequency of creation/destruction of such handles would needlessly generate Java garbage. This is also why the OpenCL bindings in LWJGL 3 use primitive handles instead of the object handles we had in LWJGL 2.
In C you would do something like
1  
2  
VkInstance instance;
vkCreateInstance(..., &instance);


The closest we can get to that is
1  
2  
VkInstance instance = new VkInstance();
vkCreateInstance(..., instance);


which is IMO better than the planned
1  
2  
3  
PointerBuffer instanceBuffer = MemoryUtil.memAllocPointer(1);
vkCreateInstance(..., instanceBuffer);
VkInstance instance = new VkInstance(instanceBuffer.get(0));



And no, don't make the non-dispatchable handles objects. I just wanted to make a point that whether they are longs or objects make no difference for us as long as the objects aren't created and destroyed/garbage collected often.

Myomyomyo.
Offline Spasi
« Reply #69 - Posted 2016-02-20 17:52:40 »

In C you would do something like
1  
2  
VkInstance instance;
vkCreateInstance(..., &instance);


The closest we can get to that is
1  
2  
VkInstance instance = new VkInstance();
vkCreateInstance(..., instance);


which is IMO better than the planned
1  
2  
3  
PointerBuffer instanceBuffer = MemoryUtil.memAllocPointer(1);
vkCreateInstance(..., instanceBuffer);
VkInstance instance = new VkInstance(instanceBuffer.get(0));

It's less typing and better looking, but sacrifices immutability of the handle instance. That's worse imho. There are also functions that create/return multiple handles and that would require passing (Java) array arguments, which is also something I'd like to avoid.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #70 - Posted 2016-02-20 17:53:21 »

Exactly like they are now, except that instead of passing (as the first parameter) a long dispatchable handle (they're always the first parameter), you pass an instance of a Java class (VkInstance, VkDevice, VkQueue, etc). Nothing else changes. There's no thread-local state and all methods are static.
Okay then. That sounds about perfect from the API side. And no lookups and the best possible performance sounds about the perfect solution! Smiley
Offline theagentd
« Reply #71 - Posted 2016-02-20 18:53:17 »

It's less typing and better looking, but sacrifices immutability of the handle instance. That's worse imho. There are also functions that create/return multiple handles and that would require passing (Java) array arguments, which is also something I'd like to avoid.
You can always mark the object as created after it has been passed into vkCreate***(), so that if it is passed in again it will throw an exception.

Are there any practical problems with passing in an array? I see no immediate problems with doing
1  
2  
VkObject[] objects = new VkObject[numObjects];
vkCreateObject(..., objects);

Myomyomyo.
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #72 - Posted 2016-02-20 22:16:29 »

If I am not mistaken, this all so far has been about VK functions returning handles to dispatchable objects, which (like their names imply) dispatch other function invocations, having them as parameters, to instance/device-specific/sensitive Vulkan functions internally. So we really only need Java objects for those dispatchable objects so that we can efficiently associate with them the needed instance/device-sensitive function pointers.
As far as I can tell, there are no other Vulkan functions that would benefit from having actual Java objects as out parameters. A single LongBuffer will suffice and the single 'long' is also what is needed. We don't need to associate more information with that 'long'.
And it also seems that those functions creating handles to dispatchable VK objects only return single instances as out parameters and not lists of objects.
Offline Spasi
« Reply #73 - Posted 2016-02-21 00:15:57 »

And it also seems that those functions creating handles to dispatchable VK objects only return single instances as out parameters and not lists of objects.

There is one, vkEnumeratePhysicalDevices.

You can always mark the object as created after it has been passed into vkCreate***(), so that if it is passed in again it will throw an exception.

Are there any practical problems with passing in an array? I see no immediate problems with doing
1  
2  
VkObject[] objects = new VkObject[numObjects];
vkCreateObject(..., objects);

On arrays: I appreciate your example, it would be nice. But it would be a lot of work to support in the generator, just for a single function (among thousands). Also, it would surprise users, a method that accepts an array instead of a buffer, when no other method does. A lot of effort has gone into LWJGL 3 to keep things consistent across all bindings, the generator is packed with compile and runtime checks because of that.

On handles: I really dislike having uninitialized objects that are later frozen. It works, but it's bad design. I think the best approach for now is to keep what we have with the PointerBuffer out-params. It's fine for the same reason having object handles is fine: it's only 5 handle types that are only going to be allocated a few times, in a few places. I'll keep thinking about it and if a better solution presents itself, we can always overload the existing methods.
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #74 - Posted 2016-02-21 00:56:24 »

And it also seems that those functions creating handles to dispatchable VK objects only return single instances as out parameters and not lists of objects.

There is one, vkEnumeratePhysicalDevices.
Ah, missed that one. Smiley
You are right, but does VkPhysicalDevice really dispatch, in a way that is relevant to LWJGL? I mean, is there something like 'vkGetPhysicalDeviceProcAddr()' ?
I think I must correct my initial statement: We actually only need object handles for VkInstance and VkDevice, since these are the only types we need to associate function pointers with. (I try to specifically stay with the usecase of dispatching to the correct function pointers here).
Everything else can stay PointerBuffer or LongBuffer.
Or did I miss yet another function? Smiley
Offline Spasi
« Reply #75 - Posted 2016-02-21 01:48:54 »

There are functions like:

1  
2  
3  
vkGetPhysicalDeviceFeatures(VkPhysicalDevice, ...);
vkQueueSubmit(VkQueue, ...);
vkBeginCommandBuffer(VkCommandBuffer, ...);

These take neither a VkInstance nor a VkDevice. They use the VkPhysicalDevice/VkQueue/VkCommandBuffe handles to dispatch the functions. It's true that a VkPhysicalDevice will have the same function pointers as the corresponding VkInstance. And VkQueues/VkCommandBuffers will have the same function pointers as the corresponding VkDevice. But we still need to use object handles, else we'd have to do inefficient look-ups.

VkPhysicalDevice, VkQueue and VkCommandBuffer will be very simple classes. E.g. this is what VkQueue looks like atm:

1  
2  
3  
4  
5  
6  
7  
public class VkQueue extends DispatchableHandle {

   public VkQueue(long handle, VkDevice device) {
      super(handle, device.getCapabilities());
   }

}

VkInstance and VkDevice creation on the other hand is much more complex, that's where the VKCapabilities instances are created using vkGetInstanceProcAddr, vkGetDeviceProcAddr, etc.
Offline theagentd
« Reply #76 - Posted 2016-02-21 01:59:41 »

Sorry to be the one who asks, but when can we expect this? I'm eager to getting back to work. xd

Myomyomyo.
Offline Spasi
« Reply #77 - Posted 2016-02-21 02:52:11 »

Nightly build 3.0.0 #29 is up, it has the handle changes and the first attempt at proper function pointer loading. The VKCapabilities class is work in progress, but the rest seem to be working well, including extensions.
Offline NegativeZero

JGO Kernel


Medals: 357
Exp: 1 month or less


Zero but not.


« Reply #78 - Posted 2016-02-21 06:02:01 »

Sorry that this isn't directly related to the conversation, but is Vulkan.

Rumour on the street (see: reddit) is that as Nintendo has recently joined Khronos, is that the new Nintendo console (Nintendo NX) will support Vulkan.

Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #79 - Posted 2016-02-21 06:09:53 »

Lmao. Get ready for 15 more mario games.

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #80 - Posted 2016-02-21 10:54:26 »

Nightly build 3.0.0 #29 is up, it has the handle changes and the first attempt at proper function pointer loading. The VKCapabilities class is work in progress, but the rest seem to be working well, including extensions.
Very very nice work, Spasi!
Those changes got rid of my manual function lookups, reduced the parameter list of many methods which took multiple dispatchables but only needed one, and I also found many many "PointerBuffer should be LongBuffer" errors along the way due to now having type-safety with the classes. Smiley
These changes feel very nice and the whole binding feels very mature already, also when compared to C code!
Offline KaiHH

JGO Kernel


Medals: 798



« Reply #81 - Posted 2016-02-21 11:32:00 »

I have but one tiny request: I think VkCommandBuffer's are going to be created a huge huge number of times in an application, since from the Vulkan perspective they are very very lightweight.
Now it would be absolutely disastrous if it made LWJGL lookup the function pointers on each instantiation. Smiley
Or just doing an instantiation of the VkCommandBuffer Java object itself is pretty bad in this case.
Since it seems that VkCommandBuffer's only really dispatch based on their owned VkDevice, could we make the VkCommandBuffer handle inside the VkCommandBuffer class mutable?
Offline Spasi
« Reply #82 - Posted 2016-02-21 12:00:13 »

Not sure about the frequency. I'm still reading the spec and writing the sample code and haven't gotten to command buffers yet. But note:

- There's vkResetCommandBuffer, you can (should?) reuse command buffers.
- Escape analysis applies to handle objects. Multiple threads building command buffers in tight loops might benefit from that.

In any case, I'll wait for input when there are real/complete Vulkan applications. If garbage generation turns out to be a problem, the current handle classes can be made mutable without breaking anything.
Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #83 - Posted 2016-02-21 18:07:18 »

Schedule a meeting (Skype..?) or something with Vulkan creators. I am sure you can hash some stuff out!

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline theagentd
« Reply #84 - Posted 2016-02-21 21:55:33 »

Has anyone gotten VK_EXT_debug_report working? It seems a lot less powerful compared to OpenGL's system, and it doesn't actually seem to catch anything.

I've got VK_LAYER_LUNARG_standard_validation added to the list of extensions and I've registered a callback with vkCreateDebugReportCallbackEXT():

1  
2  
3  
4  
5  
6  
7  
8  
         vkCreateDebugReportCallbackEXT(instance, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, new VkDebugReportCallbackEXT() {
           
            @Override
            public int invoke(int flags, int objectType, long object, long location, int messageCode, long pLayerPrefix, long pMessage, long pUserData) {
               System.err.println("ERROR OCCURED: " + MemoryUtil.memDecodeASCII(pMessage));
               return 0;
            }
         }, 0);

I can't really get this to trigger at all. Any tiny error in the parameters to any Vulkan functions just causes a complete VM crash without any output. In addition, this can't detect any problems with the instance creation in the first place.

Myomyomyo.
Offline Spasi
« Reply #85 - Posted 2016-02-21 22:55:40 »

Have you also added VK_EXT_DEBUG_REPORT_EXTENSION_NAME to the extensions list? It seems to be working fine for me, though it's indeed easy to crash and some errors don't trigger any output. This also triggers the callback for me:

1  
vkDebugReportMessageEXT(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, NULL, NULL, 0, "prefix", "message");
Offline theagentd
« Reply #86 - Posted 2016-02-22 01:52:56 »

Yeah, calling vkDebugReportMessageEXT() does trigger an error, but I have yet to see any real errors actually occurring.

Myomyomyo.
Offline HeroesGraveDev

JGO Kernel


Medals: 383
Projects: 11
Exp: 4 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #87 - Posted 2016-02-22 04:04:51 »

I've seen various reports on reddit/IRC channels saying some of the debugging functionality is broken. (annoyingly, I can't find any right now)

Offline KaiHH

JGO Kernel


Medals: 798



« Reply #88 - Posted 2016-02-22 09:04:59 »

Did you also add the enabled layers to the enabledLayerNames array when creating the VkInstance and the VkDevice? https://github.com/SaschaWillems/Vulkan/blob/master/base/vulkandebug.cpp#L9-L17

for VkInstance creation:
https://github.com/SaschaWillems/Vulkan/blob/master/base/vulkanexamplebase.cpp#L49-L50

for VkDevice creation:
https://github.com/SaschaWillems/Vulkan/blob/master/base/vulkanexamplebase.cpp#L73-L74
Offline theagentd
« Reply #89 - Posted 2016-02-22 16:02:41 »

There aren't any setters in VkPhysicalDeviceFeatures. Although that struct is gettable from Vulkan, it's also settable and passed into vkCreateDevice().


I think I'm doing everything right... I'll look into it more.

EDIT: Woohoo! I got an error!
Quote
ERROR OCCURED: Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties().
I am surprised as hell that it detected that but not all the other obvious errors I tried to introduce.......

Myomyomyo.
Pages: 1 2 [3] 4 5 ... 7
  ignore  |  Print  
 
 

 
Riven (587 views)
2019-09-04 15:33:17

hadezbladez (5533 views)
2018-11-16 13:46:03

hadezbladez (2411 views)
2018-11-16 13:41:33

hadezbladez (5794 views)
2018-11-16 13:35:35

hadezbladez (1233 views)
2018-11-16 13:32:03

EgonOlsen (4669 views)
2018-06-10 19:43:48

EgonOlsen (5688 views)
2018-06-10 19:43:44

EgonOlsen (3205 views)
2018-06-10 19:43:20

DesertCoockie (4104 views)
2018-05-13 18:23:11

nelsongames (5125 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!