Photon crashes with 32-bit version of UE4

WMask
WMask
edited January 2015 in Native
Hi.
I'm trying to integrate Photon in my UE4 game, but it crashes on 32-bit version. 64-bit version works good.
How to reproduce this crash:
1) Create simple game template for UE.4.6.1
e908567f61b5e461f6098c9d83fa86bd.jpg
2) Copy Common-cpp folder to Source/Photon and create lib folder like in PhotonDemoParticle sample
3) Modify Test.Build.cs like in PhotonDemoParticle sample
using System;
using System.IO;
using UnrealBuildTool;

public class TestPhoton : ModuleRules
{
	public TestPhoton(TargetInfo Target)
    {
        MinFilesUsingPrecompiledHeaderOverride = 1;
        bFasterWithoutUnity = true;

		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

        PrivateDependencyModuleNames.AddRange(new string[] { });

        LoadPhoton(Target);
    }

    private string ModulePath
    {
        get { return Path.GetDirectoryName(RulesCompiler.GetModuleFilename(this.GetType().Name)); }
    }

    private string PhotonPath
    {
        get { return Path.GetFullPath(Path.Combine(ModulePath, "..", "Photon")); }
    }

    private void AddPhotonLibPathWin(TargetInfo Target, string name)
    {
        string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "x64" : "Win32";
        PublicAdditionalLibraries.Add(Path.Combine(PhotonPath, "lib", "Windows", name + "-cpp_vc12_release_windows_md_" + PlatformString + ".lib"));
    }

    public bool LoadPhoton(TargetInfo Target)
    {
        if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
        {
            Definitions.Add("_EG_WINDOWS_PLATFORM");
            AddPhotonLibPathWin(Target, "Common");
        }
        else
        {
            throw new Exception("\nTarget platform not supported: " + Target.Platform);
        }

        // Include path
        PublicIncludePaths.Add(Path.Combine(PhotonPath, "."));

        return true;
    }
}
4) Add BlueprintCallable function to GameMode class
// header
class TESTPHOTON_API ATestPhotonGameMode : public AGameMode
{
	GENERATED_BODY()
public:
	//
	UFUNCTION(BlueprintCallable, Category = "Photon")
	void TestPhoton();
};
...
// source
#include "AllowWindowsPlatformTypes.h"
#pragma warning (disable: 4263)
#pragma warning (disable: 4264)

#include "Common-cpp/inc/Hashtable.h"

#pragma warning (default: 4263)
#pragma warning (default: 4264)
#include "HideWindowsPlatformTypes.h"

void ATestPhotonGameMode::TestPhoton()
{
	ExitGames::Common::Hashtable ht;
	ht.put(1, 1);
	ht.put(2, 2);
}
5) Compile and run Editor, select this ATestPhotonGameMode as a default game mode and modify Level Blueprint for testing:
874e39bcb374c039d12c991d3cd2963d.jpg
6) Build DebugGame or Shipping Win32 version of game using File->Package Project->Windows->Windows(32-bit)
7) Run it and get crash after pressing T key
8) Also you can run debug Win32 version in VS and get more detailed error:
195dd7ae2b3b2340a40fd3e345440331.jpg

I have this crash on 32-bit Build version only. Win64 version works good: no errors, no crashes.

Comments

  • Hi WMask.

    We are looking into this tomorrow.
  • Thx. Waiting for results.
  • Hi again.

    With DebugGame and also with Development I also have 64bit available, while 32bit is greyed out. How have you been able to run DebugGame in 32bit?
    When using the Shipping config, then 64bit is greyed out and only 32bit available, but the Shipping config complains, that content would not have been cooked, even after cooking content. I am currently struggling to find out how to get the Shipping config running.
    Sorry, I am not too familiar with UE4, yet.
  • Kaiserludi wrote:
    How have you been able to run DebugGame in 32bit?

    I'm using GitHub version of UE4. Version from launcher has some restrictions.

    596667b0a9fd95410658b7f36de81d20.jpg

    I think, it's better to use GitHub version. You can associate UE4 account with Github like this

    03a53e689a75f2f2745d271badc167ec.jpg

    And download engine: git clone -b 4.6 https://github.com/EpicGames/UnrealEngine D:/GutHub/UE.4.6
    Then follow 6 steps from Readme: https://github.com/EpicGames/UnrealEngine <- this link is visible only if you logged in GitHub under associated account.
    Kaiserludi wrote:
    but the Shipping config complains, that content would not have been cooked, even after cooking content. I am currently struggling to find out how to get the Shipping config running.

    Are you build Shipping version from Editor? First you should build 64-bit Editor using Development Editor option. Then you can open Editor and build any game version using it. This is my Editor settings:

    c8d2a909ecf16a174462252bb0cee146.jpg

    Then I go to File->Package Project->Windows->Windows (Win32) and run Packaging. Editor cooks content, compiles code and makes build. It cooks content automatically by default, isn't it?
    You can open console Window->Developer Tools->Output Log before packaging. This is one of the first lines of packaging:
    MainFrameActions: Packaging (Windows (32-bit)): Running AutomationTool...
    MainFrameActions: Packaging (Windows (32-bit)): Program.Main: Running on WindowsHostPlatform
    MainFrameActions: Packaging (Windows (32-bit)): Program.Main: CWD=D:\UnrealEngine\4.6\Engine\Binaries\DotNET
    MainFrameActions: Packaging (Windows (32-bit)): Automation.ParseCommandLine: Parsing command line: BuildCookRun -rocket -nocompile -installed -nop4 -project=D:/MY_PROJECTS/TestPhoton32/TestPhoton32.uproject -cook -allmaps -CrashReporter -stage -archive -archivedirectory=D:/MY_PROJECTS/TestPhoton32/Saved -package -WindowsNoEditor -clientconfig=Shipping -ue4exe=UE4Editor-Cmd.exe -pak -prereqs -targetplatform=Win32 -build -utf8output -NoCompile
    

    I think command BuildCookRun will cook content. Finally I have this files:

    9e0db1778a8d50caa7092667481919ea.jpg

    After packaging you can also run debug game from Visual Studio. It will use cooked content from previous Editor build.
  • Quick update:
    We can reproduce the crash with the github build, but have not tracked down its cause, yet.
  • Kaiserludi wrote:
    We can reproduce the crash with the github build

    Ok, my part of work is done. Hope you will fix it soon.
  • I think that I have found the cause of this issue.

    On default Visual Studio uses 8 byte alignment for packaging structs and classes in both 32 and 64bit (https://msdn.microsoft.com/en-us/library/xh3e3fd0.aspx). The normal Photon Windows libs stay with those defaults. However Unreal Engine 4 appears to use 4 byte alignment in 32bit, while staying with the 8byte VS default on 64bit, which leads into an incompatibility between UE4 and Photon due to different alignment options in 32bit, while there is no such incompatibility in 64bit.

    A new special Windows Client SDK build, with Zp set to 4 on 32bit is now available at https://dl.dropboxusercontent.com/u/429 ... bitZp8.zip
    Please give the libs from that build a try and tell us, if that helps. I can no longer reproduce the problem after switching to those libs.
  • Kaiserludi wrote:
    Please give the libs from that build a try and tell us, if that helps.

    Yes, it helps. All my projects with UE4+Photon now works well. No crashes. I think this problem is solved.
    Kaiserludi wrote:
    However Unreal Engine 4 appears to use 4 byte alignment in 32bit, while staying with the 8byte VS default on 64bit, which leads into an incompatibility between UE4 and Photon due to different alignment options in 32bit, while there is no such incompatibility in 64bit.

    Other libs have the same problem. I'm using libpqtypes in my project.
    LoadPhoton(Target);
    LoadPqLib(Target);
    

    Now Photon works good, but libpqtypes crashes inside pqt_swap8 function:
    void
    pqt_swap8(void *outp, void *inp, int tonet)
    {
    	static int n = 1;
    
    #ifdef STRICT_MEMORY_ALIGNMENT
    	unsigned int in&#91;2&#93;;
    	unsigned int out&#91;2&#93;;
    	memcpy(&in, inp, 8);
    #else
    	unsigned int *in = (unsigned int *) inp;
    	unsigned int *out = (unsigned int *) outp;
    #endif
    
    	/* swap when needed */
    	if (*(char *)&n == 1)
    	{
    		out&#91;0&#93; = (unsigned int) (tonet ? htonl(in&#91;1&#93;) : ntohl(in&#91;1&#93;));
    		out&#91;1&#93; = (unsigned int) (tonet ? htonl(in&#91;0&#93;) : ntohl(in&#91;0&#93;));
    	}
    	else
    	{
    		out&#91;0&#93; = in&#91;0&#93;;
    		out&#91;1&#93; = in&#91;1&#93;;
    	}
    
    #ifdef STRICT_MEMORY_ALIGNMENT
    	memcpy(outp, out, 8);
    #endif
    }
    

    It's time to create thread on their forum :)
  • Thanks for the good news :-)