ConfettiFX / The-Forge

The Forge Cross-Platform Rendering Framework PC Windows, Steamdeck (native), Ray Tracing, macOS / iOS, Android, XBOX, PS4, PS5, Switch, Quest 2
Apache License 2.0
4.82k stars 504 forks source link

Minimal example? #138

Closed VinnyVicious closed 5 years ago

VinnyVicious commented 5 years ago

Is there a minimal example on how to use the library? For example, a basic CMake that includes the engine and a main.cpp that shows a window and a teapot?

wolfgangfengel commented 5 years ago

I think the minimal example is 01_Transformations ... depending on the platform you are running on, you want to open it with the IDE that we support on this platform. There is also a list of platform requirements on the GitHub page. For macOS / iOS we use beta software that you would need to get. For Linux we use Ubuntu and for Android we use now Visual Studio 2017 for building it ... but you need to setup the development environment. See the list on the GitHub page ...

alanjfs commented 5 years ago

I was also looking for this.

The 01_Transformations example technically works, but it's quite lengthy (800+ lines). Perhaps more importantly, it doesn't show you how to start a new project, using The-Forge.

These are the two questions that I have at the moment, and that isn't clear from the unit test.

Attempt 1

Here's what I've tried so far.

cd c:\github
git clone https://github.com/ConfettiFX/The-Forge.git --recursive
.\The-Forge\PRE_BUILD.bat
# double-click The-Forge\Examples_3\Unit_Tests\PC Visual Studio 2017\Unit_Tests.sln
# build DebugDx

Next I'll setup a new project.

Additional Dependencies

It's unclear which of these are specific to the unit test, and which I'm meant to use.

Xinput9_1_0.lib
ws2_32.lib
gainputstatic.lib
RendererDX12.lib
OS.lib

Preprocessor Definitions

Likewise, these were part of the unit test.

USE_MEMORY_TRACKING
_DEBUG
_WINDOWS
DIRECT3D12

main.cpp

#include "Common_3/OS/Interfaces/IApp.h"

class MyApplication : public IApp
{
public:
    bool Init() override { return true; }
    void Exit() override {}

    bool Load() override { return true; }
    void Unload() override {}

    void Update(float deltaTime) override {}
    void Draw() override {}

    const char* GetName() override { return "name"; }
};

extern int WindowsMain(int argc, char** argv, IApp* app);

int main(int argc, char** argv)
{
    MyApplication app;
    return WindowsMain(argc, argv, &app);
}

With main lifted from The-Forge\Common_3\OS\Interfaces\IApp.h, as referenced in the Unit Test via the macro DEFINE_APPLICATION_MAIN(Transformations).

The issues with this so far, is that:

  1. I need the The-Forge git repo accessible and referenced from my application, which as mentioned contains not only headers but cpp files, various tools, art and the unit tests. Those things aren't necessarily useful for my application
  2. Lack of a namespace; resulting in #include Common_3... which may be The-Forge, and may be another library or even my own code. One could include the parent directory of The-Forge git repository to the Include Path, which makes it even less obvious which parts are actually referenced by any translation unit (could now include Art and Tools too).
  3. The lib files are referenced from the Unit Test directory; not ideal, but can potentially be copied out of there, except I'll need to remember doing so for each new project and each new workstation I develop on. Would have preferred and "out of source" build, where output resides at project level or outside.

The more pressing issue right now, is that this doesn't compile.

1>OS.lib(FileSystem.obj) : error LNK2001: unresolved external symbol "char const * * pszBases" (?pszBases@@3PAPEBDA)

From what I gather, this is a required global variable of any application, that depend on IFileSystem.h. This would be something worthy of mention and documentation; what does it do, when do I need it, what values does it require?

#include "Common_3/OS/Interfaces/IApp.h"
#include "Common_3/OS/Interfaces/IFileSystem.h"

const char* pszBases[FSR_Count] = {};

...

And presto, a window!

image

Next to get a triangle rendered..


Triangle

In the 01_Transformations example, Init() appears to establish all immutable state in the application, starting with setting up the renderer. I found this a great resource in deciphering the interface to implement, this would make for a great Wiki page.

...
#include "Common_3/Renderer/IRenderer.h"

Renderer* pRenderer = NULL;

...

bool Init() override
{
    // Window and Renderer setup
    RendererDesc settings = { 0 };
    initRenderer(GetName(), &settings, &pRenderer);

    if (!pRenderer)
        return false;

    return true;
    }

Which prompts for a missing WinPixEventRunTime.dll. This was created during the intial build of the Unit Test, so I'll copy that into my application build\ directory, and we're back with a white window, this time with messages about which GPU got picked, along with a message about a missing gpu.cfg.

2019-09-26 10:55:31 [MainThread     ]                log.cpp:163   INFO| Opened log file forge1.log
2019-09-26 10:55:31 [MainThread     ]        windowsbase.cpp:377   INFO| Created window app name
2019-09-26 10:55:32 [MainThread     ]         filesystem.cpp:367    ERR| Could not open file GPUCfg/gpu.cfg
2019-09-26 10:55:32 [MainThread     ]            gpuconfig.h:206   WARN| gpu.cfg could not be found, setting preset to Low as a default.
2019-09-26 10:55:32 [MainThread     ]         filesystem.cpp:367    ERR| Could not open file GPUCfg/gpu.cfg
2019-09-26 10:55:32 [MainThread     ]            gpuconfig.h:206   WARN| gpu.cfg could not be found, setting preset to Low as a default.
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1524  INFO| GPU[0] detected. Vendor ID: 10de, Revision ID: a1, GPU Name: NVIDIA GeForce GTX 1050
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1524  INFO| GPU[1] detected. Vendor ID: 8086, Revision ID: 7, GPU Name: Intel(R) UHD Graphics 620
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1560  INFO| GPU[0] is selected as default GPU
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1561  INFO| Name of selected gpu: NVIDIA GeForce GTX 1050
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1562  INFO| Vendor id of selected gpu: 0x10de
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1563  INFO| Model id of selected gpu: 0x1c8d
2019-09-26 10:55:32 [MainThread     ]         direct3d12.cpp:1564  INFO| Revision id of selected gpu: 0xa1
2019-09-26 10:55:32 [MainThread     ]        windowsbase.cpp:607   INFO| Application Init+Load 1.436000

I found The-Forge\Examples_3\Unit_Tests\src\01_Transformations\GPUCfg\gpu.cfg, but seeing as it doesn't appear necessary I'll skip this for now.

Now to figure out which parts of this unit test are necessary to draw clear the background to a nice teal color. Well, it'll probably happen in Draw().

...

void Draw() override {
    acquireNextImage(pRenderer, pSwapChain, pImageAcquiredSemaphore, NULL, &gFrameIndex);

    RenderTarget* pRenderTarget = pSwapChain->ppSwapchainRenderTargets[gFrameIndex];
    Semaphore*    pRenderCompleteSemaphore = pRenderCompleteSemaphores[gFrameIndex];
    Fence*        pRenderCompleteFence = pRenderCompleteFences[gFrameIndex];
}

The first few lines reference a few more global variables, but it's unclear which we need. At this point, as there were too many unknowns, I tried approaching it from the other direction; stripping the 01_Transformations example down to its bare essentials; just enough to clear the background with a solid color. But that proved challenging as well; there are global variables spread across each method, and hardcoded numbers like gImageCount that various parts of the file seem to depend on, and multiple arrays of objects I was unable to make sense of was initialised with like pRenderCompleteFences, pRenderCompleteSemaphores and pSkyboxUniformBuffer.

Here I could use your help. Would it be possible to fill this in, with the minimal bare essentials to get a window on the screen, with a triangle in it?

image

VinnyVicious commented 5 years ago

Awesome write up, @alanjfs. That sums it up pretty well.

alanjfs commented 5 years ago

Thanks for the kind words @VinnyVicious.

Since then, I've stopped looking at The-Forge. My current understanding is that there is no incentive for the authors of this project to provide guidance nor documentation, as they make a living off of consulting, with The-Forge as backend. If users were able to get by on their own, they would effectively lose business. As evident by there being a private GitLab and Skype where actual development and support happens; despite the appearance of public development and support via GitHub and Discord. Personally, I wish this was more apparent from the README such that users like you and me wouldn't dedicate (waste) precious time trying to decrypt it. But I wouldn't hold my breath; attention and free code reviews from an unsuspecting community are valuable assets ripe for exploitment.

I would recommend Magnum or bs::framework instead; or if you need a similar low-level wrapper, bgfx looks rather solid. Each of which have great documentation and are actually developed openly.

jdswebb commented 5 years ago

The-Forge could definitely benefit from having better documentation. I would say as things stand now you do require at least a decent knowledge of one of the modern APIs to use it effectively when you need to go beyond what is demonstrated in the examples.

I do not think there is a conspiracy to force people into paying for support though. I've used TF for a substantial personal project and the devs have always been responsive and helpful whether on Discord or otherwise. I can't speak for them but I get the impression documentation just hasn't been a priority so far.

dsrour commented 5 years ago

Hello,

We feel that the last post from @alanjfs is a bit unfair. First and foremost, we are in the transition of moving towards Discord for communication. The Discord chat is public and anyone is welcome to participate which you are more than welcome to join and ask for support there. As for Github vs Gitlab, the main reason we host our own repos in a private server is to be able to maintain and develop NDA and private code-bases in a secured fashion while still keeping a common development workflow internally. As can be seen from the Github history, any PRs that were pushed here eventually make it in the releases.

The Forge as it stands has little documentation, but we feel that the rendering interfaces should make sense to anyone having a solid grasp of newer graphics APIs. We do our best to help people when they encounter issues as can be seen in the public chats history.

As far as getting started and easily creating new projects, this is something we're still internally discussing, but is not a high priority for us at the moment. As it stands, the Forge should not be treated as a library that you'd use out of the box. The "OS" library in the samples include the majority of the Forge modules, which is not something that everyone might want. The idea is that one would use the modules that they'd want to integrate into their own projects/engine and work out the integration steps themselves....

At the moment, all the Forge modules are very low-level. We are working towards higher-level APIs as to come closer to what an "engine" would look like. As mentioned by @jdswebb, there is no conspiracy theory. We welcome constructive feedback and enjoy partaking in interesting discussions regarding software engineering, architectural decisions, and obviously graphics programming.

Best, David

alanjfs commented 5 years ago

Reading what I wrote, I think you're right, sorry, that was unfair. It's good that the source is accessible to others and that there are examples of what it looks like in the README. I just felt cheated by the first reply to this thread, "I think the minimal example is 01_Transformations". It should have said "Sorry, there are no examples and no documentation either" at which point I could have tipped my hat and saved a day of trying to decrypt what is unit test, not an example.

AntoineConffx commented 5 years ago

Hey @Kleenox,

We greatly appreciate the feedback :) If you haven't joined our Discord channel, please feel free to do so as we can provide support or help if you have any integration issues or questions.

As for D3D11 support on Windows 7 we are in the process of adding it to our internal CI setup and should be full integrated soon. This will ensure that the D3D11 runtime works as expected with the supported unit-tests.