Page 1 of 2 12 LastLast
Results 1 to 10 of 18

Thread: Pointers or not?

  1. #1

    Pointers or not?

    Simple stupid question.

    If I have declared 2 variables type of IDirect3DTexture9 and I use DirectX loader function to load image to first one of those variables.

    After that If I assign that variable which holds the texture to another variable is that image data copied to new memory location also or is that another variable just pointing to same memory space (debugger says it's a same memory space, but.....)

    For example.....

    Code:
    var
      T1: IDirect3DTexture9;
      T2: IDirect3DTexture9;
    
    begin
      T1 := Loadtexture(FileName);
    
       // Now T1 is referencing to texture in memory.
    
      T2 := T1;
    
       // is T2 referencing to same texture or is that a copy of previous one?
    
      T1._Release;
    
       // Now texture should be freed from memory, but it can be drawn by
       // using T2?!?
    end.
    - In a world without the wall and fences, who will need the Gates and Windows.

  2. #2

    Pointers or not?

    as far as I know, T2 has become a texture in it's own right but it is looking at the same memory space as T1. Except when you free T1, the image is still left in memory because it is still being referenced. T1 will be unusable but the data remains for use by T2. Correct me if I'm wrong here guys.
    Isometric game development blog http://isoenginedev.blogspot.com/

  3. #3

    Pointers or not?

    Quote Originally Posted by Crisp_N_Dry
    as far as I know, T2 has become a texture in it's own right but it is looking at the same memory space as T1. Except when you free T1, the image is still left in memory because it is still being referenced. T1 will be unusable but the data remains for use by T2. Correct me if I'm wrong here guys.
    Okey, it means that T2 isn't taking anymore memory than that IDirect3DTexture interface needs (which is 4 bytes) without texture data. Am I correct?

    So, how next example differs from earlier and why it behaves differently?

    Code:
    type
      PTexture: ^IDirect3DTexture9;    // typed pointer.
    
    var
      T1: IDirect3DTexture9;
      P1: PTexture;
    
    begin
      T1 := LoadTexture(FileName);
    
        // T1 is now referencing texture data in memory.
    
      P1 := @T1;
    
        // P1 is now referencing to same data (as T2 does in earlier example).
    
      T1._Release;
    
        // T1 is freed and so is texture data also. From now on P1 cannot be
        // used for drawing or if so then nothing is drawed.
    end.
    - In a world without the wall and fences, who will need the Gates and Windows.

  4. #4

    Pointers or not?

    Implicit reference counting.

    When you create the texture object, it sets the reference count to one. When you assign T1 to T2, T2 now points to the same texture object and it increments the reference count of that object. When you call _Release on T1, it decrements the reference count, but since the reference count is still greater than zero, the object itself is not destroyed. Therefore the texture can still be used via T2.

    Tip: Setting T1 to nil implicitly calls _Release just like setting T2 to equal T1 implicitly calls AddRef.

    In your second example, you are just getting a pointer to the pointer to the texture object. You are not creating a second reference to the texture object.

    First example
    Code:
    T1-->|
         | IDirect3DTexture9
    T2-->|
    Second example
    Code:
    P1-->T1-->IDirect3DTexture9

  5. #5

    Pointers or not?

    Quote Originally Posted by Sly
    Implicit reference counting.

    When you create the texture object, it sets the reference count to one. When you assign T1 to T2, T2 now points to the same texture object and it increments the reference count of that object. When you call _Release on T1, it decrements the reference count, but since the reference count is still greater than zero, the object itself is not destroyed. Therefore the texture can still be used via T2.

    Tip: Setting T1 to nil implicitly calls _Release just like setting T2 to equal T1 implicitly calls AddRef.

    In your second example, you are just getting a pointer to the pointer to the texture object. You are not creating a second reference to the texture object.
    Okey, thanks a lot. That makes it all clear, but one question. Which one you should recommend to if I'm making a simple game and there's TSprite class and TSpriteManager class.

    TSpriteManager loads textures for the TSprites and manages which object owns which texture and so on.

    TSprite has typed pointer to it's texture which is in dynamic array which is managed by TSpriteManager. Should that typed pointer in TSprite class be a simple variable instead of typed pointer.

    Example....

    Code:
    type
      TSpriteManager = Class
      private
          Textures: Array of IDirect3DTexture9;
      public
         LoadTexture(File);
         DeleteTexture(ID);
         Etc....
           .
           .
      end;
    
    type
      PTexture = ^IDirect3DTexture9;
    
    type
      TSprite = Class
      private
          Texture: PTexture;
      public
           Create(TextureID);
           Draw;
           Etc...
           .
           .
      end;
    
    constructor TSprite.Create(TextureID);
    begin
        
        // some pseudo code.
        Seek(TextureID) from TextureManager.
        If texture is loaded then 
            set self.texture point to that texture in manager
        else
             manager loads texture and then returns pointer to texture.
        end;
    
    end;
    So should it be typed like this or just a reference to texture? Is the memory usage same anyway?
    - In a world without the wall and fences, who will need the Gates and Windows.

  6. #6

    Pointers or not?

    Same memory usage either way.

    In your case, I would hesitate to use a pointer to a member of the array simply because you are using a dynamic array. If that array is made large through the use of SetLength(), the entire array may change location in memory, thus invalidating any pointers that currently point to items in that array. That is because they point to where the array items used to be, not where they are now.

    So in the case that you describe, I would use a IDirect3DTexture9 member in TSprite, not a PTexture. This will still be valid even if the array in TSpriteManager gets reallocated and moves in memory.

  7. #7

    Pointers or not?

    Ouh, really? I didn't know that SetLength() would change its location. Okey, then I begun to use IDirect3DTexture9 instead of pointer. Those classes on my example was very simplified, but idea is same.

    Currently I'm keeping reference count of pointers in TSpriteManager class, so when I begun to use variables instead of pointers I can get rid of keeping the book of references, because the texture stays in memory as long as any sprite variable points to it - correct? And when all sprites which references to the same texture is freed also that texture data is freed from memory - correct?

    Hey, and thanks for your answers. These have been very helpfull.
    - In a world without the wall and fences, who will need the Gates and Windows.

  8. #8

    Pointers or not?

    If each TSprite has a reference to a IDirect3DTexture9 object, then you can destroy the TSpriteManager object and each TSprite will still have its texture because they are reference counted.

    As for the SetLength() statement, think of it this way. You have the array set to 4 elements.
    Code:
    allocated|arrayx4|allocated|empty...
    Now you want to change the length of the array to 8 elements. Since we have the memory immediately after the array in use, the array cannot be made longer in-place, so the system must reallocate and copy the array.
    Code:
    allocated|empty|allocated|arrayx8|empty...
    The array moved, but your code does not realise this because it was all done behind the scenes. The array member you have in your class is not the array itself, but really a pointer to the array. Dynamic arrays work exactly the same as long strings. The system manages the allocation, reallocation, destruction of the memory used by the array/string, but you do not see this because the system has changed your pointer to point to the correct location in memory.

  9. #9

    Pointers or not?

    Ah, you are soooooo right. I appreciate your answers. Thanks very much,
    - In a world without the wall and fences, who will need the Gates and Windows.

  10. #10

    Pointers or not?

    Yes. Spr2 is pointing to the same object that Spr1 is, so moving Spr2 would move Spr1.

    Ok. Keep your TSpriteManager. It will deal with creating the TSprite objects so it can give each TSprite instance a reference to the texture.

    [pascal]
    type
    TSprite = class
    private
    FTexture: IDirect3DTexture9;
    public
    constructor Create(ATexture: IDirect3DTexture9);
    destructor Destroy; override;
    end;

    TSpriteManager = class
    private
    FTextures: TStringList;
    function LoadTexture(FileName: String): IDirect3DTexture9;
    function FindTexture(FileName: String): IDirect3DTexture9;
    public
    constructor Create;
    destructor Destroy; override;
    function CreateSprite(FileName: String): TSprite;
    end;

    implementation

    { TSprite }

    constructor TSprite.Create(ATexture: IDirect3DTexture9);
    begin
    { Get a reference to the texture }
    FTexture := ATexture;
    end;

    destructor TSprite.Destroy;
    begin
    { Release the reference to the texture }
    FTexture := nil;
    inherited;
    end;

    { TSpriteManager }

    constructor TSpriteManager.Create;
    begin
    FTextures := TStringList.Create;
    end;

    destructor TSpriteManager.Destroy;
    begin
    while FTextures.Count > 0 do
    begin
    IDirect3DTexture9(FTextures.Objects[0])._Release;
    FTextures.Remove(0);
    end;
    FTextures.Free;
    inherited;
    end;

    function CreateSprite(FileName: String): TSprite;
    var
    Texture: IDirect3DTexture9;
    begin
    { Have we already loaded this texture? }
    Texture := FindTexture(FileName);
    { If not, the load it }
    if Texture = nil then
    Texture := LoadTexture(FileName);
    { Create the TSprite and give it a reference to the texture }
    Result := TSprite.Create(Texture);
    { Release the reference to the texture }
    Texture := nil;
    end;

    function TSpriteManager.LoadTexture(FileName: String): IDirect3DTexture9;
    begin
    Result := {however you load your texture};
    { Add the texture and filename to the list for later use }
    FTextures.AddObject(FileName, Pointer(Result));
    end;

    function TSpriteManager.FindTexture(FileName: String): IDirect3DTexture9;
    var
    Texture: IDirect3DTexture9;
    Index: Integer;
    begin
    Result := nil;
    { Is the texture in the list? }
    Index := FTextures.IndexOf(FileName);
    if Index > -1 then
    Result := IDirect3DTexture9(FTextures.Objects[Index]);
    end;
    [/pascal]

    Note that this code is off-the-top-of-my-head, so it may contain some errors.

    To create a sprite, call SpriteManager.CreateSprite(FileName). This will search through the list of textures that have already been loaded. If the texture is found, it gives the sprite a reference to that texture, otherwise it creates a new texture.

    Hope that helps. I use a similar (but more extensive) system in my own project. I have a base TResource class and a TResourceManager that is used as the basis for everything (textures, materials, fonts, meshes, etc).

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •