Gamestudio Links
Zorro Links
Newest Posts
Change chart colours
by 7th_zorro. 05/11/24 09:25
Data from CSV not parsed correctly
by dr_panther. 05/06/24 18:50
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
1 registered members (Ayumi), 662 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Newest Members
Hanky27, firatv, wandaluciaia, Mega_Rod, EternallyCurious
19051 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 4 of 5 1 2 3 4 5
Re: How to make a copy of a bmap? [Re: WretchedSid] #367614
04/15/11 13:53
04/15/11 13:53
Joined: Aug 2005
Posts: 238
Caermundh Offline OP
Member
Caermundh  Offline OP
Member

Joined: Aug 2005
Posts: 238
@Schubido:

Good catch on the memory leak. I hadn't thought of that. I'll definitly tweak the code to not do that. I cant use bmap_createblack to set pixels because I've found out I need to copy a source bitmap to a target bmap without creating a new bitmap. Here's what I'm currently doing to copy the bmap:

Code:
function *bmap_copy(BMAP* target_bmp, BMAP* source_bmp)
{   target_bmp.width = source_bmp.width;
    target_bmp.height = source_bmp.height;
    target_bmp.bytespp = source_bmp.bytespp;
    target_bmp.flags = source_bmp.flags;
    target_bmp.u1 = source_bmp.u1;
    target_bmp.v1 = source_bmp.v1;
    target_bmp.u2 = source_bmp.u2;
    target_bmp.v2 = source_bmp.v2;
    target_bmp.u = source_bmp.u;
    target_bmp.v = source_bmp.v;
    target_bmp.refcount = source_bmp.refcount;
    target_bmp.finalwidth = source_bmp.finalwidth;
    target_bmp.finalheight = source_bmp.finalheight;
    target_bmp.finalbytespp = source_bmp.finalbytespp;
    target_bmp.pitch = source_bmp.pitch;
    target_bmp.finalpitch = source_bmp.finalpitch;
    target_bmp.miplevels = source_bmp.miplevels;
    target_bmp.finalformat = source_bmp.finalformat;
    target_bmp.finalbits = NULL;
    target_bmp.d3dtex = NULL;
    target_bmp.pixels = malloc((source_bmp.width*source_bmp.height)*source_bmp.bytespp);
    memcpy(target_bmp.pixels, source_bmp.pixels, (source_bmp.width*source_bmp.height)*source_bmp.bytespp);
}



Do you think free(target_bmp.pixels); would work?

@HeelX:

Schubido had actually suggested using bmap_blit() to copy the bmap earlier in the thread. I decided against using blit because of concerns over the speed of the command.

I also think i've figured out the cause of the invalid pointer freed error message when exiting the game - its because im setting d3dtex to NULL - Gamestudio is expecting something to be there. I just have to figure out the format of whats stored at d3dtex (or at least how to figure the *size* of whats stored there) and I can copy it. That should fix the error.

Last edited by Caermundh; 04/15/11 14:14.
Re: How to make a copy of a bmap? [Re: Caermundh] #367623
04/15/11 15:46
04/15/11 15:46
Joined: Jan 2002
Posts: 4,225
Germany / Essen
Uhrwerk Offline
Expert
Uhrwerk  Offline
Expert

Joined: Jan 2002
Posts: 4,225
Germany / Essen
Originally Posted By: Caermundh
In the future, I will avoid asking "why didnt that work?" style questions like I did in the later posts of this thread.

That is not the problem. The problem is, that you seem to be advice-resistant. So here is my last comment concerning this topic. Go with HeelXs solution. It's clean, effective and fast - maybe even faster than yours. Your solution is error prone and has at least one other memory leak you haven't noticed yet. Several other problems might arise from it.


Always learn from history, to be sure you make the same mistakes again...
Re: How to make a copy of a bmap? [Re: Caermundh] #367629
04/15/11 17:19
04/15/11 17:19
Joined: Nov 2010
Posts: 96
Vienna
S
Schubido Offline
Junior Member
Schubido  Offline
Junior Member
S

Joined: Nov 2010
Posts: 96
Vienna
Quote:
Do you think free(target_bmp.pixels); would work?



You could try, but I would not expect it to work properly. You don't know how memory allocation is done within the GS functions. I guess its not malloc (get memory from OS), but maybe an internal heap management. This could also be the reason why you got a "invalid pointer freed" error when exiting the game. Why do I think so? Because a message like this would be the expected behaviour if GS calls an internal (not OS!) free function for a pointer to memory which is allocated with standard malloc.
However - its just guessing.

Therefore I agree with Uhrwerk and the rest of the gang;) not to deal with GS internals. Even if you solve it, there is no guerantee that it works in all configurations or with the next update.
Have you done a performance test with bmap_blit? I think HeelX code should do the job perfectly.
If this is really to slow (how many copies do you produce??) you could try to "ask the developers" if there is a way to do it faster.

Re: How to make a copy of a bmap? [Re: Schubido] #367654
04/16/11 07:24
04/16/11 07:24
Joined: Jul 2001
Posts: 6,904
H
HeelX Offline
Senior Expert
HeelX  Offline
Senior Expert
H

Joined: Jul 2001
Posts: 6,904
Originally Posted By: Schubido
Have you done a performance test with bmap_blit? I think HeelX code should do the job perfectly.
I designed a stress test to discover the time consumed by both cases bmap_blit (CPU) and -process (GPU). I create the same amount of copies of bitmaps with both methods and count the consumed time with dtimer(). For each iteration I create a new bitmap to avoid engine-optimizations like not overwriting the source image pointer for the shader because the image pointer has not been changed since the last call of bmap_process.

The following test calculates the mean processing time for both methods for 100 iterations for a 512x512x24 image:

Code:
#include <acknex.h>
#include <stdio.h>

BMAP* bmap_clone (BMAP* src);
BMAP* bmap_cloneGPU (BMAP* src);

int main()
{
   wait(1);
   
   int iterations = 100;
   int width = 512, height = 512, format = 24;
   
   double t_cpu = 0;
   
      int i;
      for (i = 0; i < iterations; i++)
      {
         BMAP* b = bmap_createblack(width,height,format); // src
         
         dtimer();
         BMAP* c = bmap_clone(b);
         t_cpu += dtimer();
         
         ptr_remove(b);
         ptr_remove(c);       
      }

   t_cpu /= (double)iterations;
   
   double t_gpu = 0;
   
      int i;
      for (i = 0; i < iterations; i++)
      {
         BMAP* b = bmap_createblack(width,height,format); // src
         
         dtimer();
         BMAP* c = bmap_cloneGPU(b);
         t_gpu += dtimer();
         
         ptr_remove(b);
         ptr_remove(c);
      }
   
   t_gpu /= (double)iterations;

   char log [512];
   sprintf(log, "bitmap = %dx%dx%d\niterations = %d\nbmap_clone (CPU) ~ %f microsecs\nbmap_clone (GPU) ~ %f microsecs", width, height, format, iterations, t_cpu, t_gpu);
   error(log);
}

BMAP* bmap_clone (BMAP* src)
{
   // no source?
   if (src == NULL)
      return(NULL);
      
   var format = bmap_lock(src, 0);
   
   // invalid bitmap or unknown format?
   if (format == 0)
      return(NULL);
   else  
      bmap_unlock(src);
   
   BMAP* r = bmap_createblack(src->width, src->height, format);
   
   if (r != NULL)
      bmap_blit(r, src, NULL, NULL);
   
   return(r);
}

MATERIAL* mtlCopy =
{
   effect = "
      
      Texture TargetMap; // src
      sampler2D smpSrc = sampler_state
      {
         texture = <TargetMap>;
      };

      float4 PS (float2 Tex: TEXCOORD0): COLOR
      {
         return(tex2D(smpSrc, Tex.xy));
      }

      technique t
      {
         pass p
         {
            AlphaBlendEnable = false;
            PixelShader = compile ps_2_0 PS();
         }
      }
   ";
}

BMAP* bmap_cloneGPU (BMAP* src)
{
   // no source?
   if (src == NULL)
      return(NULL);
      
   var format = bmap_lock(src, 0);
   
   // invalid bitmap or unknown format?
   if (format == 0)
      return(NULL);
   else  
      bmap_unlock(src);
   
   BMAP* r = bmap_createblack(src->width, src->height, format);
   
   if (r != NULL)
   {
      bmap_process(r, src, mtlCopy);
   }
   
   return(r);
}



Here are my results for a 512x512x24 bitmap on my system:

iterations = 1
bmap_clone (CPU) ~ 14110.593750 microsecs
bmap_clone (GPU) ~ 19934.037109 microsecs

iterations = 5
bmap_clone (CPU) ~ 14125.698242 microsecs
bmap_clone (GPU) ~ 8372.354492 microsecs

iterations = 100
bmap_clone (CPU) ~ 14442.785156 microsecs
bmap_clone (GPU) ~ 4864.554688

iterations = 1000
bmap_clone (CPU) ~ 14664.015625 microsecs
bmap_clone (GPU) ~ 4767.796875 microsecs

You can see, that working with bmap_blit is always around 14k microsecs. Using bmap_process has obviously an initial overhead, because after using it first time, it takes even longer than with bmap_blit. The mean time consumed by taking bmap_process to copy the bitmap is being dramatically reduced after the very first iterations and reduced to a mean time of around 5k microsecs or less. Over the time, bmap_process consumes roughly 1/3 of the time which is needed for copying with bmap_blit.

There are still open questions, like how much time is consumed by bmap_lock to get the format in order to create a new bitmap in correspondence to the source image and if the mean time of bmap_process will increase if another shader is used in between (possible overhead for changing shader code).

Conclusion: If you need performance and do lots of bitmap operations which can be done in a fragment shader, go with bmap_process!

Re: How to make a copy of a bmap? [Re: HeelX] #367678
04/16/11 14:53
04/16/11 14:53
Joined: Mar 2006
Posts: 3,538
WA, Australia
J
JibbSmart Offline
Expert
JibbSmart  Offline
Expert
J

Joined: Mar 2006
Posts: 3,538
WA, Australia
Shaders aren't normally compiled until the first time they're used. I think that's likely the biggest part of the initial overhead. My test results varied a lot, although even with lower iterations GPU beat CPU (that's just because my GPU's a beast). But if I called the bmap_cloneGPU function early so that the shader would be compiled, even just one iteration took much less time.

Jibb


Formerly known as JulzMighty.
I made KarBOOM!
Re: How to make a copy of a bmap? [Re: JibbSmart] #367683
04/16/11 16:34
04/16/11 16:34
Joined: Jul 2001
Posts: 6,904
H
HeelX Offline
Senior Expert
HeelX  Offline
Senior Expert
H

Joined: Jul 2001
Posts: 6,904
Ah I forgot the compilation time needed for shaders smile thanks, Julz!

Re: How to make a copy of a bmap? [Re: HeelX] #367696
04/16/11 20:28
04/16/11 20:28
Joined: Aug 2005
Posts: 238
Caermundh Offline OP
Member
Caermundh  Offline OP
Member

Joined: Aug 2005
Posts: 238
I went and did some tests on bmap_blit() vs bmap_copy(). I ran the following:

Code:
PANEL* info_panel =
{   pos_x = 20;
    pos_y = 20;
    flags = SHOW;
    digits = 0,0,3.0,standard_font,1,test;
    digits = 0,10,3.0,standard_font,1,test2;
}

BMAP* original_bmap = "jug_icon.tga";
BMAP* clone_bmap;

function *bmap_copy(BMAP* target_bmp, BMAP* source_bmp)
{   target_bmp.width = source_bmp.width;
    target_bmp.height = source_bmp.height;
    target_bmp.bytespp = source_bmp.bytespp;
    target_bmp.flags = source_bmp.flags;
    target_bmp.u1 = source_bmp.u1;
    target_bmp.v1 = source_bmp.v1;
    target_bmp.u2 = source_bmp.u2;
    target_bmp.v2 = source_bmp.v2;
    target_bmp.u = source_bmp.u;
    target_bmp.v = source_bmp.v;
    target_bmp.refcount = source_bmp.refcount;
    target_bmp.finalwidth = source_bmp.finalwidth;
    target_bmp.finalheight = source_bmp.finalheight;
    target_bmp.finalbytespp = source_bmp.finalbytespp;
    target_bmp.pitch = source_bmp.pitch;
    target_bmp.finalpitch = source_bmp.finalpitch;
    target_bmp.miplevels = source_bmp.miplevels;
    target_bmp.finalformat = source_bmp.finalformat;
    target_bmp.finalbits = NULL;
    target_bmp.d3dtex = NULL;
    target_bmp.pixels = malloc((source_bmp.width*source_bmp.height)*source_bmp.bytespp);
    memcpy(target_bmp.pixels, source_bmp.pixels, (source_bmp.width*source_bmp.height)*source_bmp.bytespp);
}

function main()
{   var count = 0;
    clone_bmap = bmap_createblack(32,32,24);
    timer();
    while(count<1000)
    {   bmap_copy(clone_bmap,original_bmap);
        count += 1;
    }
    test = timer();
    count = 0;
    timer();
    while(count<1000)
    {   bmap_blit(clone_bmap,original_bmap,NULL,NULL);
        count += 1;
    }
    test2 = timer();
}



Not the most accurate test in the world, i realize, but i just wanted to get a rough idea of how fast bmap_copy vs bmap_blit would be. i found that 1000 calls to bmap_copy took ~950 microseconds and 1000 calls to bmap_blit took ~947 microseconds.

So bmap_blit really is a fast (even slightly faster) than using memcpy directly. I find that more than a little surprising considering that it has to be doing more than just a simple memcpy(). I'm also not understanding why the manual says that the bmap_blit command is slow. memcpy() is about as fast as it gets, and bmap_blit is at least as fast as it - how is that a "slow" command?

Anyways, since bmap_blit *is* as fast as a memcpy() and doesnt have any of the problems that bmap_copy() has, i'm definitly using HeelX's solution. Thank you all for all the advice.

Re: How to make a copy of a bmap? [Re: Caermundh] #367701
04/16/11 21:31
04/16/11 21:31
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline
Expert
WretchedSid  Offline
Expert

Joined: Apr 2007
Posts: 3,751
Canada
bmap_blit is not implemented in Lite-C but in C++ and thus could profit from the compilers optimization.
Considering that the Lite-C compiler probably does zero to nothing optimizations with your code, its not really a surprise that bmap_blit() is faster than memcpy()

(I assume that Lite-Cs memcpy is an actual, non inlined, function)


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: How to make a copy of a bmap? [Re: WretchedSid] #367703
04/16/11 22:16
04/16/11 22:16
Joined: Aug 2005
Posts: 238
Caermundh Offline OP
Member
Caermundh  Offline OP
Member

Joined: Aug 2005
Posts: 238
memcpy() is not a lite-c function - its a C function, like malloc() and free(). If bmap_blit is implemented in C++, then its working at the same level as memcpy() so of course its going to be just as fast. That would explain it.

I wonder if all bmap_blit is doing is just a memcpy itself? I find the nearly identical run times for the two different commands to be a little suspicious.

I also still am wondering why the manual categorizes the speed of this command as "slow"? - its obviously not slow.

Re: How to make a copy of a bmap? [Re: Caermundh] #367704
04/16/11 23:14
04/16/11 23:14
Joined: Jan 2002
Posts: 4,225
Germany / Essen
Uhrwerk Offline
Expert
Uhrwerk  Offline
Expert

Joined: Jan 2002
Posts: 4,225
Germany / Essen
Originally Posted By: Caermundh
I wonder if all bmap_blit is doing is just a memcpy itself?

Yeah, sure, that's just what it does. memcpy, programmers first choice in copying and scaling bitmaps since 1872.


Always learn from history, to be sure you make the same mistakes again...
Page 4 of 5 1 2 3 4 5

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1