x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

C++ - Updating texture data

Hi guys,

we're currently updating a texture every frame and I was wondering if there was a faster form of this bit of code here:

             void* TextureData = newtex->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
             FMemory::Memcpy(TextureData, uncompressedBGRA->GetData(), uncompressedBGRA->Num());
             newtex->PlatformData->Mips[0].BulkData.Unlock();
 
             
             // Update the rendering resource from data.
             newtex->UpdateResource();
             //Put window texture in here
             ChangeTexture(newtex);

We're running this bit of code several times a frame (depending on how many textures we need to update) and I'm curious as to whether or not:

a) moved to another thread (from what I understand, updating UObjects is not to be done outside of the main rendering thread

b) whether there's a faster / more efficient form of this code. Basically assigning an array of bytes to a texture.

Thanks, -Paul

Product Version: UE 4.12
Tags:
more ▼

asked Aug 03 '16 at 02:27 AM in Rendering

avatar image

ozzadar
17 5 9 13

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

I would setup a texture like this:

 // create dynamic texture
 m_pDynamicTexture = UTexture2D::CreateTransient(TEX_WIDTH, TEX_HEIGHT, TEX_PIXEL_FORMAT);
 m_pDynamicTexture->UpdateResource();

 m_pDynamicTexture->AddressX = TEX_ADDRESS_X;
 m_pDynamicTexture->AddressY = TEX_ADDRESS_Y;
 m_pDynamicTexture->Filter = TEX_FILTER;
 m_pDynamicTexture->RefreshSamplerStates();

setup with a dynamic material instance using UMaterialInstanceDynamic::SetTextureParameterValue, then update it like this:

 ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
     UpdateDynamicTextureCode,
     UTexture2D*, pTexture, m_pDynamicTexture,
     const uint8*, pData, pData,
     {
         FUpdateTextureRegion2D region;
 region.SrcX = 0;
 region.SrcY = 0;
 region.DestX = 0;
 region.DestY = 0;
 region.Width = TEX_WIDTH;
 region.Height = TEX_HEIGHT;

 FTexture2DResource* resource = (FTexture2DResource*)pTexture->Resource;
 RHIUpdateTexture2D(resource->GetTexture2DRHI(), 0, region, region.Width * TEX_PIXEL_SIZE_IN_BYTES, pData);
     });


Hope it helps!

more ▼

answered Aug 04 '16 at 08:52 PM

avatar image

Vadaumuku
86 4 11

avatar image ozzadar Aug 05 '16 at 05:40 AM

This looks solid, though I have a few questions:

1) What is TEX_ADDRESS_X, TEX_ADDRESS_Y ? I'm already using a dynamic texture and it's assigned though im not using these parameters. 2) Where does ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER go, and how does it reference m_pDynamicTexture ? It looks to me as if you're redefining m_pDynamicTexture in ENQUEUE; am I reading it wrong? Also, can this macro be called from a FRunnable thread? 3) What is UpdateDynamicTextureCode ?

Sorry if I seem lost. I'll be anxiously awaiting your reply and will be researching myself in the meantime. Maybe I'll be able to figure it out :)

avatar image Shohei Aug 05 '16 at 05:58 AM

I believe those are simply macros for a TextureAddress TEnumAsByte value. If I understand correctly these are things like Clamp, Wrap, Mirror, etc..

avatar image ozzadar Aug 05 '16 at 06:08 AM

So ive been playing around and I figured out 2) and 3).... it seems that I can't reference variables from within the macro so how do I obtain TEXTURE_PIXEL_SIZE_IN_BYTES ?

avatar image ozzadar Aug 05 '16 at 06:18 AM

would TEXTURE_PIXEL_SIZE_IN_BYTES be sizeof(EPixelFormat::[...]) ?

avatar image Vadaumuku Aug 05 '16 at 06:21 AM

No :)

TEXTURE_PIXEL_SIZE_IN_BYTES depends on your pixel format (ex: use 4 for PF_R8G8B8A8 pixel format, use 2 for PF_R8G8, ...).

avatar image ozzadar Aug 05 '16 at 07:59 AM

Thanks a ton! You just took my game from 15fps to 60fps.

You're the man. Took a minute to figure out what the problem was with my array allocation but I got her done and award you a million digital brownies

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1) The address mode tells how the textures is sampled outside 0..1 texture coordinate range. The valid values are TA_WRAP, TA_CLAMP & TA_MIRROR. If you're not familiar with texture addressing don't bother with them. I bet the default values will work just fine.

2 & 3) Add the ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER into your tick function. It will schedule a command to run on the rendering thread for avoiding CPU/GPU synchronizations. Because of this, you can't use the same pData for each frame (the rendering thread might lag behind).

It's best to do something like:

 YourClass:Tick(float deltaTime)
 {
     uint16* pData = new uint16[pitch * h * 3];
     //*** FILL pData HERE ***//

     ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
         UpdateDynamicTextureCode,
         UTexture2D*, pTexture, m_pDynamicTexture,
         const uint8*, pData, pData,
         {
             FUpdateTextureRegion2D region;
         region.SrcX = 0;
         region.SrcY = 0;
         region.DestX = 0;
         region.DestY = 0;
         region.Width = TEX_WIDTH;
         region.Height = TEX_HEIGHT;

         FTexture2DResource* resource = (FTexture2DResource*)pTexture->Resource;
         RHIUpdateTexture2D(resource->GetTexture2DRHI(), 0, region, region.Width * TEX_PIXEL_SIZE_IN_BYTES, pData);
         delete[] pData;
         });
 }


more ▼

answered Aug 05 '16 at 06:10 AM

avatar image

Vadaumuku
86 4 11

avatar image Vadaumuku Aug 05 '16 at 06:12 AM

TEXTURE_PIXEL_SIZE_IN_BYTES depends on your pixel format (ex: use 4 for R8G8B8A8 pixel format).

avatar image ozzadar Aug 05 '16 at 06:45 AM

Alright, so I think I've got it set up right.

I seem to be hitting an error:

Unhandled exception at 0x00007FF9986C9959 (nvwgf2umx.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0x0000021666060800

I imagine this means some of the data im passing it isn't working correctly?

edit:: it breaks on the line

ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(

avatar image Vadaumuku Aug 05 '16 at 07:03 AM

1) Make sure your texture is dynamic 2) The command scheduled by ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER will execute at a later time, from the rendering thread. Make sure you don't delete pData before it gets used.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question