Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for cross compiling for Windows on ARM with Visual Studio #104

Closed
wants to merge 2 commits into from

Conversation

hmartinez82
Copy link

@hmartinez82 hmartinez82 commented Oct 5, 2023

Comments:

  • SSE2NEON is a header-only library. It was copied and pasted, but git submodules could be used if preferred. This is their repo: https://github.com/DLTcollab/sse2neon
  • /Zc:preprocessor is needed for sse2neon, but since the public API surface of Spout does not include the intrinsic headers this won't affect upstream code that uses Spout2

Fixes #102

@hmartinez82 hmartinez82 marked this pull request as ready for review October 5, 2023 08:22
@hmartinez82
Copy link
Author

hmartinez82 commented Oct 5, 2023

And it works \o/
image
Note that both processes are Arm64 and not emulated 🚀

@leadedge
Copy link
Owner

leadedge commented Oct 6, 2023

This is excellent.

The only thing that bothers me is the prominence of the "sse2neon" folder and ongoing questions about why it's there, in which case I would need an answer. Practically, how do you see Spout being used on an Arm device? Is other graphics software supported where Spout or Syphon are frequently used, such as for visuals or projection? Resolume, TouchDesigner, Unreal Engine, OBS etc..

Minor changes and additions (I can change these).

If sse2neon only supports sse2, in SpoutCopy "CheckSSE", m_bSSE3 and m_bSSSE3 should be false.

SpoutSenderNames.cpp - move includes into SpoutSenderNames.h where they should be anyway.

SpoutGL "OpenSpout" to indicate 64 or 32 bit build can be :
if defined _M_X64 || defined _M_ARM64

The readme file located one level above should notify that the include path for sse2neon is only defined if CMake is used, conditions for sse2neon MIT licence must be met and notice for Visual Studio only.

@hmartinez82
Copy link
Author

hmartinez82 commented Oct 6, 2023

This is excellent.

The only thing that bothers me is the prominence of the "sse2neon" folder and ongoing questions about why it's there, in which case I would need an answer. Practically, how do you see Spout being used on an Arm device? Is other graphics software supported where Spout or Syphon are frequently used, such as for visuals or projection? Resolume, TouchDesigner, Unreal Engine, OBS etc..

In this case, the app that is being ported to Windows on ARM is Stellarium: https://github.com/Stellarium/stellarium and they use Spout2.

Do you prefer to use sse2neon as a git submodule instead of just copying the file there?

Minor changes and additions (I can change these).

If sse2neon only supports sse2, in SpoutCopy "CheckSSE", m_bSSE3 and m_bSSSE3 should be false.

In sse2neon, that 2, does not mean two, it means to
As in: SSE to NEON

From their project: sse2neon aims to support SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AES extension. :-)

SpoutSenderNames.cpp - move includes into SpoutSenderNames.h where they should be anyway.

Isn't it better to keep all usages of sse2neon in implementation files so there's no risk of if ever making into the public API surface of the library?

SpoutGL "OpenSpout" to indicate 64 or 32 bit build can be : if defined _M_X64 || defined _M_ARM64

You mean this line? https://github.com/leadedge/Spout2/pull/104/files#diff-cbd7e61a03bf22527a1ce0fd81ec96d61570e09f5fb5d0abbe973262875a3ef1R509 ? You prefer to not differentiate 64 bits from 64bits ARM?

The readme file located one level above should notify that the include path for sse2neon is only defined if CMake is used, conditions for sse2neon MIT license must be met and notice for Visual Studio only.

Is it possible to build this library without CMake?
Also, Clang, when compiling for Windows on ARM, also defines _M_ARM64

@leadedge
Copy link
Owner

leadedge commented Oct 6, 2023

Yes I have looked at the Stellarium port and I understand that this development would be key to it's success and perhaps for other projects to follow. What application is going to receive from it? Do you have something in mind or in development?

What I was wondering was whether the arm laptop could be used for other purposes without porting applications. I understand there is an emulator for existing x86 applications to be run. If so, texture sharing might work because it's external to the application itself.

Using a git submodule is a step too far at the moment.

OK I understand now that 2 means "to", so all of these should work. In particular the high speed SSE3 copy functions.

I have never considered public API surface. From my understanding, whether it's in the cpp file or the header it's still open, the same way as for SpoutCopy.h.

It's no use to differentiate 64 bits from 64 bits ARM unless texture sharing works with an emulator as I mentioned above. Then the log would indicate whether native application or emulator.

Yes you can build without CMake with a Visual Studio solution or equivalent and I originally had Visual Studio solutions as well as CMake. But I was advised to remove the solution files in favour of a purely CMake build.

I forsee questions about using other compilers, but I can't support them. From what you say, if _M_ARM64 is defined for Clang, the build would succeed. I think a modification of wording to that effect should do it, so that the responsibility is shifted to the user.


Edit
There is a solution for CMake to download sse2neon.h. I have it working.
What I will do is make the necessary changes and commit, then modify as required after testing.


All the updated files are now in the beta branch. Hopefully everything is in place for a CMake build for Arm. I moved the __movsd definition from "sse2neon.h" into "SpoutCommon.h".

@hmartinez82
Copy link
Author

We can close this PR then? :)

@leadedge
Copy link
Owner

leadedge commented Oct 8, 2023

Yes it can be closed. I hope I have all the amendments right. Changes are minor.

It would be good if you could confirm successful build with CMake using the new "SPOUT_BUILD_ARM" option. sse2neon.h should be downloaded and the folder created for the rest of the build.

I note that Stellarium is using SpoutLibrary. If that works, the rest will too.

This is a significant addition and thanks for your interest and work in putting it together.

@hmartinez82
Copy link
Author

hmartinez82 commented Oct 8, 2023

The download of SSE2NEON didn't work. The contents of the .h file is not C, it's

{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".ci","path":".ci","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":"tests","path":"tests","contentType":"directory"},{"name":".clang-format","path":".clang-format","contentType":"file"},...

I think you wanted the raw URL? https://github.com/DLTcollab/sse2neon/raw/master/sse2neon.h

@hmartinez82
Copy link
Author

I've refreshed this PR with the sole fix

@leadedge
Copy link
Owner

leadedge commented Oct 8, 2023

Many thanks indeed. I will do that by hand and test it here.
I presume it works OK otherwise.

@hmartinez82
Copy link
Author

@leadedge It's compiling now after those two commits, \o/
image
Btw, I forgot to mention. The receiver above is x64 and the sender is ARM64, so x-arch sender/receiver works

@leadedge
Copy link
Owner

leadedge commented Oct 8, 2023

OK, that's significant. It means that any Spout enabled application will communicate with natively compiled applications.

Also, x64 "SpoutSettings" should also work and set up the registry that ARM apps will read. I was thinking that a console application would be needed.

Having run x64 "SpoutSettings" to set up the path for "SpoutPanel", what happens if you RH mouse click on the x64 receiver window. The x64 "SpoutPanel" sender selection dialog should come up. Can you select the ARM sender as well as x64 demo sender?

This looks good. Thanks again. Leave it with me and I will test the changes here.

@hmartinez82
Copy link
Author

God! Stellarium is using a 7 year old local copy of SpoutLibrary.h (the public API surface for Spout2) and pre-compiled DLLs. Wish me luck updating that😅

@hmartinez82
Copy link
Author

Right clicking in the receiver, which is x64, resulted into this:
image

@hmartinez82
Copy link
Author

Ah, I forgot to run SpoutSettings. Let me try that first.

@hmartinez82
Copy link
Author

It worked. After running SpoutSettings at least once, right clicking the Receiver:
image

@leadedge
Copy link
Owner

leadedge commented Oct 8, 2023

That means the x86 applications are working as they normally would and an ARM built receiver should also pop up x86 "SpoutPanel".

Because the sender information is in shared memory and the shared textures are also external to the application, all should be seamless.

I have pushed the two changes.

Edit
The SpoutLibrary update should work straight away.

@leadedge
Copy link
Owner

leadedge commented Oct 9, 2023

It looks like all is good.

Now that we know that there can be a mix of Arm and x86 Spout applications I have put the log line back in.
All should be up to date, so I leave it to you to close the PR if you are happy with the changes.

@hmartinez82 hmartinez82 closed this Oct 9, 2023
@hmartinez82 hmartinez82 deleted the ARM64 branch October 9, 2023 00:59
@leadedge
Copy link
Owner

I wonder could you try this version of SpoutPanel.
If you click on the sender texture details, it should report the executable build type.

SpoutPanel_261_build-test.zip

@hmartinez82
Copy link
Author

hmartinez82 commented Oct 12, 2023

Hum... it's not working for ARM64. It only shows the sender CPU type for x64:
image
Left, ARM64, right x64

@leadedge
Copy link
Owner

For some reason, the sender executable path is not being saved to the sender shared memory for Tutorial04. That's a separate problem. Otherwise it is showing the system CPU and "8cx" which is the machine type. It's almost working I think. I will have a look at why the executable path isn't being saved.

@hmartinez82
Copy link
Author

Shouldn't it say ARM64 ?

@leadedge
Copy link
Owner

Yes it should, but the executable path is missing as you can see at the bottom "Sender application" and it can't read the file header and PE signature. I think it should work if it could read that file. Give me a bit and I will find out what is happening.

@hmartinez82
Copy link
Author

Understood. I can't find SpoutPanel source code.

@leadedge
Copy link
Owner

That isn't public, and it links to other programs that are also not public but you are welcome to a copy once I sort this out a little.

@hmartinez82
Copy link
Author

Understood. I'll wait for the next executable then :)

@leadedge
Copy link
Owner

I changed SpoutPanel to make it clear if the sender executable path is not found. Here is a test version.

I can't find out why it isn't found. It might have something to do with permissions or the emulated process environment.

I changed SpoutDX to use "GetModuleFileNameEx" instead of "GetModuleFileName" and "Tutorial04" should be re-built to activate it.

I don't think this will make any difference, so I changed the SpoutSettings Performance "Check" button to include a report for the executable build. This should be enough for tracing user problems.

@hmartinez82
Copy link
Author

😅
image

@hmartinez82
Copy link
Author

hmartinez82 commented Oct 13, 2023

Yep. Still does not show the path.
I wonder if you have the process id of the sender and then you could use QueryFullProcessImageName(). For example:

    DWORD processId = 1234; // Replace with your desired PID

    // Open a handle to the target process
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
    if (hProcess == NULL) {
        std::cerr << "Failed to open process. Error code: " << GetLastError() << std::endl;
        return 1;
    }

    // Get the size of the buffer required for the image path
    DWORD bufferSize = MAX_PATH;
    WCHAR imagePath[MAX_PATH];

    if (QueryFullProcessImageNameW(hProcess, 0, imagePath, &bufferSize)) {
        // QueryFullProcessImageNameW succeeded, and the image path is stored in 'imagePath'.
        std::wcout << L"Image path: " << imagePath << std::endl;
    } else {
        // QueryFullProcessImageNameW failed
        std::cerr << "Failed to get the image path. Error code: " << GetLastError() << std::endl;
    }

    // Close the handle to the process
    CloseHandle(hProcess);

@leadedge
Copy link
Owner

leadedge commented Oct 13, 2023

That's a good suggestion. I tried it and it works OK. There were other methods as well that I rejected for some reason or other.

The problem is not with SpoutPanel, but with the sender itself. To find out, you would have to re-build the Tutorial04 example for ARM with the current beta branch files.

SpoutDX "CheckSender" is the function in question. Presently it uses "GetModuleFileNameEx". Please download that version before I push a version with "QueryFullProcessImageName".

Meanwhile please confirm that SpoutPanel reports "No sender executable path", and that the SpoutSettings "Check" button reports the executable build.

The links I gave are for files that I can change or delete later rather than uploading them to a post. They are hosted within GitHub in https://github.com/leadedge/leadedge.github.io/tree/downloads. If you are still uncomfortable I will upload to a post.

As you know, Windows security typically complains about zip files.

I am ignoring this, as well as anti-virus false positives. There is no way I will pay somebody to give a certificate that does nothing just to avoid it.

@hmartinez82
Copy link
Author

Yes, of course. It was just funny the popup.
Understood. I need to rebuild the latest Beta branch.
I'll do that later and let you know

@leadedge
Copy link
Owner

Here are the latest SpoutPanel and SpoutSettings. I am wasting GiHub server space by attaching them here but it seems necessary.

I think that the SpoutSetiings "Check" button is enough, but it would be nice if the sender build could be shown by the receiver directly.

Apologies if by last reply was abrupt, but anti-virus is a major headache. I can't get rid of the Bkav warning for SpoutPanel in VirusTotal so that's the way it has to remain. Even a minimal program generated by Visual Studio itself generates warnings from 3 companies.

SpoutPanel-SpoutSettings_16-10-23.zip

@hmartinez82
Copy link
Author

With that one I get:
image
when the sender is ARM64

@leadedge
Copy link
Owner

Many thanks for your time. This shows a clean report if the executable path is not found.

For some reason, the sender is not writing the executable path to shared memory. If it's an ARM sender, that eliminates problems with emulation and I don't know what the reason could be.

I haven't had time to change to your suggestion to retrieve the executable path. Currently GetModuleFileNameExA is used so "QueryFullProcessImageNameA" should be a drop-in replacement.

At line 2039, "exepath" should be "exepath[0]" but it would pass here anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants