Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (521)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (589)
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
  ignore  |  Print  
  PBuffers sharing textures without a Display()  (Read 3985 times)
0 Members and 1 Guest are viewing this topic.
Offline javazoid

Junior Devvie




Where's Flender?


« Posted 2005-01-11 08:06:12 »

-----------------------------------------------------------
SHORT VERSION:
-----------------------------------------------------------


From the docs
NOTE: The Pbuffer will have its own context that shares display lists and textures with the Display context (if it is created).


How can I share textures and display lists between PBuffers without creating a Display() ?

-----------------------------------------------------------
LONG VERSION:
-----------------------------------------------------------


I'm going on with my SGL  (Simple Graphics Library) which is more or less a simple lwjgl based Java2D replacement.

It already draws polys and animated images (textured quads) with affinetransforms, alpha compositing etc. It will handle java2d shapes soon. SGL makes wide use of PBuffers.

The speed is fantastic and the API is really simple. Here's a sample:

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  
            SGLBitmap sb0 = new SGLBitmap(512,256,0);
            SGLBitmap sb1 = new SGLBitmap(220,200,0);
            SGLImage si = new SGLImage(bufferedimage);
           
           
            int loops = 1000;
            sb0.startTimer();
            for (int i=0; i<loops; i++)
            {
                  sb0.setTransform(AffineTransform.getRotateInstance(-i/10f,100,50));
                  sb0.setColor(new Color(220,11,11,10));
                  sb0.fillRect(0,0,180,120);
                  sb0.setColor(Color.white);
                  sb0.drawRect(0,0,190,130);
                  sb0.setColor(new Color(220,240,150,12));
                  sb0.fillRect(20,20,110,120);
                  sb0.drawImage(si,30,10);
                 
                  sb1.setColor(Color.blue);
                  sb1.fillRect(0,0,80,20);
                  sb1.setColor(Color.yellow);
                  sb1.drawRect(0,0,90,30);
                  sb1.drawImage(si,0,0);
            }
            float t = sb0.endTimer();



Now I discovered that the PBuffers constructed without a Display do not share textures and display lists and that's a problem as they must be shared between SGLBitmaps (each SGLBitmap holds a PBuffer).


From the docs
NOTE: The Pbuffer will have its own context that shares display lists and textures with the Display context (if it is created).


As SGL will work both onscreen and offscreen, I would need to share display lists and textures without creating a Display().

Maybe the LWJGL Pbuffers constructor would need a boolean switch in order to allow the sharing of display lists and textures.

Offline princec

« JGO Spiffy Duke »


Medals: 421
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2005-01-11 09:55:16 »

I ought to point out that display lists are broken in a number of cheapass GL drivers.

Cas Smiley

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #2 - Posted 2005-01-11 11:07:23 »

No problems with glists or poor drivers. I'll have a fallback-to-java2d mode in case of problems.

The main question remains the same: how can I share textures and display lists between PBuffers without creating a Display() ?

I suppose this involves a little change in LWJGL, isn't it ? I think it would be a nice feature.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline elias

Senior Devvie





« Reply #3 - Posted 2005-01-11 11:10:30 »

*POOF* - wish granted. You can now specify a Pbuffer to share with in the Pbuffer constructor.

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #4 - Posted 2005-01-11 11:21:19 »

FABULOUS  Shocked

Where can I download the new magic ?

Offline elias

Senior Devvie





« Reply #5 - Posted 2005-01-11 12:33:09 »

You can fetch a version here:

http://odense.kollegienet.dk/~naur/lwjgl_11012005.zip

I didn't bother testing it though, since I'm doing a lot of other lwjgl related work at the moment.

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #6 - Posted 2005-01-11 12:38:40 »

Thanks Elias,

I'll give it a run. I hope to see the new feature in the official distribution soon.

Cheers,

Mik

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #7 - Posted 2005-01-13 06:36:08 »

Hi Elias,

it seems that the new Pbuffer shared contex does not work.

here's my initialization code:


Code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
 

   static Pbuffer sc_pbuffer = null;
 
   // create the first shared-context tiny pbuffer
   if (sc_pbuffer == null)
   {
    sc_pbuffer = new Pbuffer(1, 1, new PixelFormat(8, 24, 0, samples), null, null);
    sc_pbuffer.makeCurrent();
   }
   
   // allocate the pbuffer
   pbuffer = new Pbuffer(width, height, new PixelFormat(8, 24, 0, samples), null, sc_pbuffer);
   pbuffer.makeCurrent();


Mik

Offline elias

Senior Devvie





« Reply #8 - Posted 2005-01-13 11:07:36 »

I need more than that. Is there an error message? If not, are the textures not shared? If they aren't, does it work if you create a Display first?

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #9 - Posted 2005-01-13 11:35:00 »

Using the "new" Pbuffer shared context:

- No error messages.
- Textures are not shared.

Using the "usual" Display shared context:

- No error messages.
- Textures shared correctly.
- Error message if I try to create a Pbuffer with another Pbuffer context after initializing the Display (ok: this works as expected).
The message:
org.lwjgl.LWJGLException: Could not share buffer context.
     at org.lwjgl.opengl.Win32Display.nCreatePbuffer(Native Method)
     at org.lwjgl.opengl.Win32Display.createPbuffer(Win32Display.java:115)
     at org.lwjgl.opengl.Pbuffer.createPbuffer(Pbuffer.java:187)

Mik

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline elias

Senior Devvie





« Reply #10 - Posted 2005-01-13 11:51:29 »

Strange. However, from the docs for wglShareLists it seems that only new objects are shared. Have you tried this sequence:

1. Create a pbuffer
2. Create another pbuffer shared with the first
3. Create a texture in pbuffer1 and render it from pbuffer2.

Does that work?

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #11 - Posted 2005-01-13 12:05:37 »


That's exacly what I'm doing:

- create sc_Pbuffer with a null shared pbuffer reference.

- create Pbuffer0 with a reference to sc_Pbuffer
- create textures
- create Pbuffer1 with a reference to sc_Pbuffer
- make Pbuffer0 current
- draw textures
- make Pbuffer1 current
- draw textures

the textures only appear in Pbuffer0







Offline elias

Senior Devvie





« Reply #12 - Posted 2005-01-14 05:39:54 »

Quote

That's exacly what I'm doing:

- create sc_Pbuffer with a null shared pbuffer reference.

- create Pbuffer0 with a reference to sc_Pbuffer
- create textures
- create Pbuffer1 with a reference to sc_Pbuffer
- make Pbuffer0 current
- draw textures
- make Pbuffer1 current
- draw textures

the textures only appear in Pbuffer0



Not quite. You need to try to create textures _after_ both pbuffer0 and pbuffer1 has been created (and shared). Better yet, try to limit the case to only pbuffer0 and pbuffer1, leaving out the sc_pbuffer.

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #13 - Posted 2005-01-14 05:54:02 »

I did almost any kind of try. It doesn't work.

The only way to make it work is to open a Display first, which is of course not a solution (well at least for me).

Offline Spasi
« Reply #14 - Posted 2005-01-14 07:42:58 »

Quote
You need to try to create textures _after_ both pbuffer0 and pbuffer1 has been created (and shared).


Wow, are you sure? I didn't know that. Is that the case with normal framebuffer-pbuffer sharing too?
Offline elias

Senior Devvie





« Reply #15 - Posted 2005-01-14 08:24:38 »

I'm not sure, I'm just trying to narrow down the possible causes.

- elias

Offline elias

Senior Devvie





« Reply #16 - Posted 2005-01-14 09:05:27 »

Javazoid: As an alternative implementation, have you considered having one single pbuffer and a texture for each image? If you draw on one image at a time it will have the same cost. If you draw on multiple images, they will have to be drawn to the pbuffer first (and the old one transferred to its texture).

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #17 - Posted 2005-01-14 09:11:48 »

I have several Pbuffers wrapped into SGLBitmaps. they have different sizes and I can draw textures (SGLImages) to one of them at unpredictable times.

SGLImages themselves can be allocated everywhere in the code and still they can be traced into any allocated SGLBitmap. This makes the sharedcontext so important.

Offline elias

Senior Devvie





« Reply #18 - Posted 2005-01-14 10:02:47 »

Yes, I understand that. What I was trying to say is why not make the SGLBitmaps textures too and only use one pbuffer (and therefore one context)? When a SGLBitmap is being used, it need to draw itself onto the pbuffer first if it is not already there. The old SGLImage on the pbuffer will need to be flushed to its texture. And finally, if some SGLBitmap is created that is larger than the current pbuffer, flush it and re-create a pbuffer of the right size. The OpenGL drivers are probably more tuned to multiple textures than to multiple pbuffers anyway.

- elias

Offline elias

Senior Devvie





« Reply #19 - Posted 2005-01-14 10:09:41 »

Oh, and remember that Pbuffer contents can be lost, while textures are always preserved.

- elias

Offline elias

Senior Devvie





« Reply #20 - Posted 2005-01-14 11:09:31 »

Anyway, I think I fixed a bug in the win32 implementation. My test case now works on all platforms. Grab it here:

http://odense.kollegienet.dk/~naur/lwjgl_14012005.zip

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #21 - Posted 2005-01-14 11:28:15 »

I'm going to send you the sources of my implementation. It's pretty straighforward.  Send me an email address at mik@classx.it

I'm very new to OpenGL sorry. Anyway you are suggesting me to enable render-to-texture on my Pbuffers ?

That's what I've got:
- create a Pbuffer (one static instance).
- SGLBitmap holds a texture which is the one that must be bound to the Pbuffer.
- SGLImage holds a texture. This one is constructed my making the PBuffer current.
- SGLBitmap.drawImage(SGLImage) will draw the texture to the Pbuffer.
- I can grab the SGLBitmap texture pixels through glGetTexImage() from the texture bound to the Pbuffer.

Mmmh, some nice things:
- I couldn't care less if the PBuffer loses its contents.
- no context switch. Very good for speed.

the bad: I have to rewrite everything.

Q: if the design above is right, can you tell me how glGetTexImage() perform compared to glReadPixels() ?

Mik


PS your http://odense.kollegienet.dk/~naur/lwjgl_14012005.zip  WORKS very well! MANY THANKS!

Offline princec

« JGO Spiffy Duke »


Medals: 421
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #22 - Posted 2005-01-14 11:31:40 »

GetTexImage = very very fast, copies from VRAM to VRAM.
ReadPixels = very very slow, reads the wrong way across the AGP buffer, aaaagh!

Cas Smiley

Offline elias

Senior Devvie





« Reply #23 - Posted 2005-01-14 11:45:16 »

That's more or less right I think. To clarify, I'd probably make a SGLBitmap and SGLImage the same, say, SGLGraphics. It would work something like this:

- As an initialization, create the singleton pbuffer and make it current. There's no context switches from now on, since that single pbuffer is always used.
- The "active" SGLGraphics is stored as a singleton variable along with the pbuffer. This is for caching.
- When a WGLGraphics is constructed, it is assigned a texture id.
- SGLGraphics.flush() uses either render-to-texture or simply glCopyTexImage2D to copy the contents of the pbuffer to its texture. Render-to-texture is very fast, but even glCopyTexImage2D should be much faster than glReadPixels or glGetTexImage().
- SGLGraphics.makeActive() uses a quad or something to draw the entire SGLGraphics texture onto the pbuffer, ready for changes. Additionally, it sets the active SGLGraphics to itself.
- SGLGraphics.drawSomething() does the following:
        1. if (this != active_sglgraphics) {
                 active_sglgraphics.flush();
                 makeActive();
            }
        2. Draw the desired texture or primitive.

To actually get at the pixel data from a SGLGraphics you'll need to use glGetTexImage.

Hope that makes it clear.

- elias

Offline elias

Senior Devvie





« Reply #24 - Posted 2005-01-14 11:50:37 »

Quote
GetTexImage = very very fast, copies from VRAM to VRAM.
ReadPixels = very very slow, reads the wrong way across the AGP buffer, aaaagh!

Cas Smiley


Cas is slightly wrong here. GetTexImage and ReadPixels are probably equally fast, depending on whether the texture is cached in system ram or not. It's CopyTexImage2D that is (potentially) VRAM to VRAM and therefore fast.

- elias

Offline javazoid

Junior Devvie




Where's Flender?


« Reply #25 - Posted 2005-01-14 12:02:34 »

Thanks for the hints.
What happens if the several SGBraphics have different sizes ? I would be forced to re-allocate the PBuffer, right ?

Offline Spasi
« Reply #26 - Posted 2005-01-14 12:20:22 »

I'd like to add that render-to-texture is not an option in such a system, because:

A) When pbuffer contents get lost, the texture contents will be lost too. render-to-texture is more appropriate for dynamic textures that get refreshed each frame.
B) How can multiple textures be created from a single render-to-texture pbuffer? Only by making it huge and packing multiple images. Not very nice.

So, CopyTexImage should be the best option and more than fast enough too.
Offline princec

« JGO Spiffy Duke »


Medals: 421
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #27 - Posted 2005-01-14 12:50:18 »

Thanks for the correction smartass Wink

Cas Smiley

Offline Spasi
« Reply #28 - Posted 2005-01-14 17:22:54 »

Elias, your last change broke getPbufferCaps, it always returns 0. Pbuffers work great if you ignore it though.
Offline javazoid

Junior Devvie




Where's Flender?


« Reply #29 - Posted 2005-01-15 08:19:25 »

Elias,

I implemented the SGLGraphics as suggested. There was a little design problem in your description. No problem, I fixed it today.

I benchmarked both implementations with 20000 loops of misc graphics:

2 bitmap/graphics switches per loop

SGLGraphics gives:
Time s. 11.46202
Fps.    1744.8932

SGLBitmap:
Time s. 9.126782
Fps.    2191.3528

4 bitmap/graphics switches per loop

SGLGraphics gives:
Time s. 22.803085
Fps.    877.0743

SGLBitmap:
Time s. 14.629756
Fps.    1367.0768

From the numbers the SGLBitmap seems to be quite better. The reason is the number of graphics copys from/to the pbuffer needed from SGLGraphics.

Even more, with SGLGraphics, when the pbuffer loses it contents, even the textures in its context go away. This forces me to reallocate  every texture in the "new" pbuffer (including the SGLGraphics backbuffer).

From the SGLBitmap side, when the pbuffer gets lost I can recreate it and ask SGLImages to re-create their textures at drawImage() time.

Anyway, the Pbuffers shared context works as expected and this is a great feature.

However Pbuffer flushing is still a problem. For this reason I would suggest what I call a "missing feature": create an invisible Display  i.e. by putting a boolean in the constructor and a pair of hide()/show() methods.

This would be useful in order to share the Display context between subsequent Pbuffer allocations in order to keep the textures when the Pbuffers get lost. Nice, isn't it ?

Pages: [1] 2
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xFryIx (60 views)
2014-11-13 12:34:49

digdugdiggy (39 views)
2014-11-12 21:11:50

digdugdiggy (32 views)
2014-11-12 21:10:15

digdugdiggy (28 views)
2014-11-12 21:09:33

kovacsa (50 views)
2014-11-07 19:57:14

TehJavaDev (54 views)
2014-11-03 22:04:50

BurntPizza (53 views)
2014-11-03 18:54:52

moogie (68 views)
2014-11-03 06:22:04

CopyableCougar4 (67 views)
2014-11-01 23:36:41

DarkCart (153 views)
2014-11-01 14:51:03
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!