Announcement

Collapse
No announcement yet.

[Plugin]Texture Issue EDIT: How to make sure UTexture2D gets converted to a FTexture2DRHIRef)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    [Plugin]Texture Issue EDIT: How to make sure UTexture2D gets converted to a FTexture2DRHIRef)

    Hey all,
    I am generating a plugin to generate water wave interaction with any geometry. I have 2 setups to detect intersection of any object with a plane to generate a mask.
    1) In the first setup I'm using SDFs to detect collision.
    2) My second setup has me shooting 512 async rays and detecting the collision that way. This way works in generating the texture and will work for cases where people don't have platforms that support SDF generation. This is then converted to pixmap and then into a UTexture2D using Rama's code.

    I want to pass this generated mask to my compute shader which at the moment just generates and updates a structured buffer and RHITexture with my input Mask. I do this via a custom blueprint function. This blueprint function is called after the Texture is generated and sent to my custom event. My program continuously crashes after I connect the generated UTexture2D. My log says it runs through the blueprint atleast once and then crashes the second time around (I have print flags to tell me issues).

    I believe it's my generated 2DTexture because I can attach a random texture and my compute shader works completely fine.
    I display my Generated 2DTexture and it displays fine without being attached to the compute shader.

    Link to my github project : https://github.com/som1990/UE4_20ShaderPluginDev

    Step 1) Below is my blueprint network for my Trace Generation. I pass it to a custom event called "Compute Height Map"
    Click image for larger version  Name:	TraceGeneration.png Views:	1 Size:	141.0 KB ID:	1668722

    Step2) Below is the blueprint to my Compute Shader function

    Click image for larger version  Name:	Add_Heightmap_2_CS.png Views:	1 Size:	53.5 KB ID:	1668723

    Here is the snippet of my Load Height Map Source ( To see more of the code check these files here , here and here )

    Code:
    void ACSTestSim::LoadHeightMapSource(float _magnitude, float _delTime, UTexture2D* SourceMap, FColor DisplayColor)
    {
        check(IsInGameThread());
        if (SourceMap->GetSizeX() != texSizeX || SourceMap->GetSizeY() != texSizeY)
        {
            UE_LOG(ComputeLog, Error, TEXT("Set Dimensions don't match input texture map. Returning."));
            bIsTextureDimensionsSet = false;
            return;
    
        }
        if (!bIsTextureDimensionsSet)
        {
            UE_LOG(ComputeLog, Warning, TEXT("TextureDimensions are not Set. Returning"));
            return;
        }
        //GEngine->AddOnScreenDebugMessage(-1, 0.2, FColor::Yellow, TEXT("Magnitude: ") + FString::SanitizeFloat(_magnitude));
    
        if (InputTexture != NULL)
        {
            InputTexture.SafeRelease();
            InputTexture = NULL;
            UE_LOG(ComputeLog, Warning, TEXT("InputTexture Reset."));
        }
    
        if (SourceMap)
        {
            InputTexture = static_cast<FTexture2DResource*>(SourceMap->Resource)->GetTexture2DRHI();
            UE_LOG(ComputeLog, Warning, TEXT("RHITexture2D Extracted, Dimensions: %d, %d"), SourceMap->GetSizeX(), SourceMap->GetSizeY());
            testComputeShader->ExecuteComputeShader(InputTexture, DisplayColor, _magnitude, _delTime);
    
            //FlushRenderingCommands();
            UE_LOG(ComputeLog, Warning, TEXT("Shader Computed."));
        }
    
    }
    ExecuteComputeShader code below
    Code:
    void FComputeTestExecute::ExecuteComputeShader(FTexture2DRHIRef _InTexture, FColor DisplayColor, float _mag, float _delTime)
    {
        check(IsInGameThread());
    
        if (!bSimulatorInitialized)
        {
            return;
        }
    
        if (bIsUnloading || bIsComputeShaderExecuting)
            return;
        bIsComputeShaderExecuting = true;
        if (InputTexture != _InTexture)
        {
            bMustRegenerateSRV = true;
        }
    
    
        InputTexture = _InTexture;
        inColor = FLinearColor(DisplayColor.R / 255.0, DisplayColor.G / 255.0, DisplayColor.B / 255.0, DisplayColor.A / 255.0);
        UE_LOG(InternalShaderLog, Warning, TEXT("Shader Variables Initialized"));
    
        m_VariableParameters.mag = _mag;
        m_VariableParameters.deltaTime = _delTime;
    
        FComputeTestExecute* MyShader = this;
        ENQUEUE_RENDER_COMMAND(ComputeShaderRun)(
            [MyShader](FRHICommandListImmediate& RHICmdList)
            {
                MyShader->ExecuteComputeShaderInternal(RHICmdList);
            }
        );
    
    
    }
    
    void FComputeTestExecute::ExecuteComputeShaderInternal(FRHICommandListImmediate& RHICmdList)
    {
        check(IsInRenderingThread());
    
        if (bIsUnloading)
        {
            ClearInternalData();
            return;
        }
    
        if (bMustRegenerateSRV)
        {
            bMustRegenerateSRV = false;
            if (NULL != InTextureSRV)
            {
                InTextureSRV.SafeRelease();
                InTextureSRV = NULL;
            }
    
            InTextureSRV = RHICreateShaderResourceView(InputTexture, 0);
        }
    
    
        TShaderMapRef<FAddSourceHeightCS> ComputeShader(GetGlobalShaderMap(FeatureLevel));
        RHICmdList.SetComputeShader(ComputeShader->GetComputeShader());
    
        ComputeShader->SetParameters(RHICmdList, inColor, InTextureSRV, InputTexture);
        ComputeShader->SetOutput(RHICmdList, TextureUAV, h0_phi0_UAV);
        ComputeShader->SetUniformBuffers(RHICmdList, m_VariableParameters);
        //RHICmdList.DispatchComputeShader(InputTexture->GetSizeX()/8, InputTexture->GetSizeY()/8,1);
        DispatchComputeShader(RHICmdList, *ComputeShader, FMath::CeilToInt(InputTexture->GetSizeX() / NUM_THREADS_PER_GROUP), FMath::CeilToInt(InputTexture->GetSizeY() / NUM_THREADS_PER_GROUP), 1);
        ComputeShader->UnbindBuffers(RHICmdList);
    
        bIsComputeShaderExecuting = false;
    }
    Code:
    Here is the logfile as it shows it runs the function once based on the log statements.
    [2019.09.27-20.33.31:683][850]Display: HotReload took  3.9s.
    [2019.09.27-20.33.33:435][955]LogTemp: Repeating last play command: Selected Viewport
    [2019.09.27-20.33.33:445][955]LogBlueprintUserMessages: Early PlayInEditor Detection: Level '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel' has LevelScriptBlueprint '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel.TestAsyncRaycastCollision' with GeneratedClass '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision_C' with ClassGeneratedBy '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel.TestAsyncRaycastCollision'
    [2019.09.27-20.33.33:445][955]LogPlayLevel: PlayLevel: No blueprints needed recompiling
    [2019.09.27-20.33.33:456][955]PIE: New page: PIE session: TestAsyncRaycastCollision (Sep 27, 2019, 10:33:33 AM)
    [2019.09.27-20.33.33:456][955]LogPlayLevel: Creating play world package: /Game/RayCastMethods/UEDPIE_0_TestAsyncRaycastCollision
    [2019.09.27-20.33.33:459][955]LogPlayLevel: PIE: StaticDuplicateObject took: (0.002688s)
    [2019.09.27-20.33.33:459][955]LogAIModule: Creating AISystem for world TestAsyncRaycastCollision
    [2019.09.27-20.33.33:460][955]LogPlayLevel: PIE: World Init took: (0.000743s)
    [2019.09.27-20.33.33:460][955]LogPlayLevel: PIE: Created PIE world by copying editor world from /Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision to /Game/RayCastMethods/UEDPIE_0_TestAsyncRaycastCollision.TestAsyncRaycastCollision (0.003581s)
    [2019.09.27-20.33.33:513][955]LogInit: XAudio2 using 'LC55LBU591U (2- NVIDIA High Definition Audio)' : 2 channels at 48 kHz using 16 bits per sample (channel mask 0x3)
    [2019.09.27-20.33.33:524][955]LogInit: FAudioDevice initialized.
    [2019.09.27-20.33.33:567][955]LogLoad: Game class is 'MyGameMode_C'
    [2019.09.27-20.33.33:569][955]LogWorld: Bringing World /Game/RayCastMethods/UEDPIE_0_TestAsyncRaycastCollision.TestAsyncRaycastCollision up for play (max tick rate 60) at 2019.09.27-15.33.33
    [2019.09.27-20.33.33:569][955]LogWorld: Bringing up level for play took: 0.000611
    [2019.09.27-20.33.33:596][955]LogContentBrowser: Native class hierarchy updated for 'MovieSceneCapture' in 0.0003 seconds. Added 10 classes and 0 folders.
    [2019.09.27-20.33.33:596][955]ComputeLog: Warning: SourceTexture, Dimensions: 512, 512
    [2019.09.27-20.33.33:596][955]ComputeLog: Warning: OutTexture Extracted, Dimensions: 512, 512
    [2019.09.27-20.33.33:606][955]PIE: Play in editor start time for /Game/RayCastMethods/UEDPIE_0_TestAsyncRaycastCollision 1.153
    [2019.09.27-20.33.33:607][955]LogBlueprintUserMessages: Late PlayInEditor Detection: Level '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel' has LevelScriptBlueprint '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel.TestAsyncRaycastCollision' with GeneratedClass '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision_C' with ClassGeneratedBy '/Game/RayCastMethods/TestAsyncRaycastCollision.TestAsyncRaycastCollision:PersistentLevel.TestAsyncRaycastCollision'
    [2019.09.27-20.33.33:733][961]ComputeLog: Warning: RHITexture2D Extracted, Dimensions: 512, 512
    [2019.09.27-20.33.33:733][961]InternalShaderLog: Warning: Shader Variables Initialized
    [2019.09.27-20.33.33:733][961]ComputeLog: Warning: Shader Computed.
    For my Trace function and texture generation please visit here . I suspect the problem lies in the generation of texture. But not sure.

    You can see my texture generating properly without being attached to the compute shader.


    What's the best solution to overcome this problem. I would prefer not to use a delay function and have it call the compute directly after the intersection mask. Maybe I make my mask via compute? Please any help would be appreciated.
    Regards,
    Soumitra Goswami
    Attached Files
    Last edited by Somz1990; 09-27-2019, 05:36 PM.

    #2
    Ok kinda figured out my problem. My UTexture2D (generated via CreateTransient) is not generating Texture2DRHIRef. It's making it null. Is there a reason for it? The UTexture2D does display a texture in render when attached to a material (As seen in the image in prev post). How do I make sure the UTexture2D can generate a Texture2DRHIRef.
    Below is how I'm generating the UTexture2D from a list of pixeldata.
    Code:
    void AIntersectionToRT::GenerateRTFromTrace_Internal(const int32 srcWidth, const int32 srcHeight, const TArray<FColor> &SrcData, const bool UseAlpha)
    {
    
    
        //GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Green, TEXT("After: ") + FString::FromInt(sizeof(Texture)));
    
        //GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, TEXT("Size: ") + FString::FromInt(srcWidth) + TEXT(", ") + FString::FromInt(srcHeight));
        uint8* MipData = static_cast<uint8*>(Texture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
    
        uint8* DestPtr = NULL;
        const FColor* SrcPtr = NULL;
        for (int32 y = 0; y < srcHeight; y++)
        {
            DestPtr = &MipData[(srcHeight - 1 - y) * srcWidth * sizeof(FColor)];
            SrcPtr = const_cast<FColor*>(&SrcData[(srcHeight - 1 - y)* srcWidth]);
            for (int32 x = 0; x < srcWidth; x++)
            {
                *DestPtr++ = SrcPtr->B;
                *DestPtr++ = SrcPtr->G;
                *DestPtr++ = SrcPtr->R;
                if (UseAlpha)
                {
                    *DestPtr++ = SrcPtr->A;
                }
                else
                {
                    *DestPtr++ = 0xFF;
                }
                SrcPtr++;
            }
        }
    
        Texture->PlatformData->Mips[0].BulkData.Unlock();
        Texture->UpdateResource();
    }
    Last edited by Somz1990; 09-28-2019, 03:55 PM.

    Comment

    Working...
    X