Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

David_pb

Community-Fossil

  • »David_pb« ist der Autor dieses Themas

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

11

19.03.2015, 09:56

Na das ist ja toll, dass der JETZT rauskommt. :rolleyes:


Naja, als early Preview zu Vulkan, ist doch ganz nett! :)
@D13_Dreinig

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

12

19.03.2015, 14:46

Ja, so sehe ich das auch. Da kann man sich schonmal darauf einstellen, was auf einem zukommt.
Ich habe jetzt nur mal so durch die Referenz gescrollt, aber da kommt bei mir schon wieder irgendwie schon ein starkes Bedürfnis nach den neuen APIs auf. Man würde am liebsten jetzt umsteigen können. :pinch:
Ich setzt inzwischen große Hoffnungen in Vulkan. Dadurch, dass AMD ihre API zur Verfügung gestellt hat, sieht es danach aus, als ob daraus auch tatsächlich etwas werden würde.

Julién

Alter Hase

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

13

20.03.2015, 16:19

Wo findet man das SDK, bzw. die Header jetzt eigentlich für Mantle?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Tobiking

1x Rätselkönig

  • Private Nachricht senden

14

20.03.2015, 17:02

Wo findet man das SDK, bzw. die Header jetzt eigentlich für Mantle?

Nirgends. Das Release wurde zu Gunsten von DX 12 und Vulkan gecancelt. Es werden nur noch die Entwickler unterstützt, die bereits Mantle in ihren Spielen eingesetzt haben.

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

15

20.03.2015, 17:24

Tja dann ist es auch keine brauchbar Preview, wenn es nicht für alle verfügbar ist.
Aber gut so, wer will schon vom "Treiberhorror" AMD einen Standard? Lieber einheitlich machen und Vulkan nutzen.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

16

20.03.2015, 20:54

Aber gut so, wer will schon vom "Treiberhorror" AMD einen Standard?


Wenn Leute keine Ahnung haben...
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

David_pb

Community-Fossil

  • »David_pb« ist der Autor dieses Themas

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

17

21.03.2015, 08:59

Tja dann ist es auch keine brauchbar Preview


Doch, die Vulkan API wird ja sehr ähnlich sein. Viele (alle) Konzepte wird es dort geben, die Ähnlichkeit zieht sich bis auf die Schnittstelle runter. Von daher ist die Doku ein äußerst brauchbares Preview um sich mit der Materie vertraut zu machen.
@D13_Dreinig

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

18

21.03.2015, 12:07

Ok an die Doku hatte ich nicht gedacht.

@Nimelrian: da macht jeder seine eigenen Erfahrungen.

David_pb

Community-Fossil

  • »David_pb« ist der Autor dieses Themas

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

19

23.03.2015, 14:48

Ok an die Doku hatte ich nicht gedacht.


Wenn du eine halbwegs aktuelle AMD Karte mit neuem Treiber hast, kannst du auch mit Mantle entwickeln. Die API ist ja komplett aufgeführt, du musst dir quasi nur die Header selbst zusammenbauen. Als 'proof of concept' hab ich das mal schnell ausprobiert, rausgekommen ist dieses quick 'n dirty 'Hello World' Programm, das nichts anderes tut als Mantle zu initialisieren und einen schwarzen Backbuffer in ein Fenster zu blitten. :)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "mantle.h"

#include <windows.h>
#include <cassert>
#include <cstdio>
#include <malloc.h>

struct InitAndLoadMantle
{
    InitAndLoadMantle()
    {
        load();
    }

private:
    bool load()
    {
        HMODULE hModule = LoadLibrary(L"mantle64.dll");
        if (!hModule)
            return false;

        // ....

        return true;
    }
};

InitAndLoadMantle GManlteInstance;

#define CHECKED_CALL(call) if (call != GR_SUCCESS) assert(false && #call " failed...");

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }

    return 0;
}

HWND createWindow()
{
    HINSTANCE hInst = GetModuleHandle(NULL);
    WNDCLASS wc = 
    {
        CS_HREDRAW | CS_VREDRAW,
        WndProc,
        0, 0,
        hInst,
        LoadIcon(NULL, IDI_APPLICATION),
        LoadCursor(NULL, IDC_ARROW),
        GetSysColorBrush(COLOR_BTNFACE),
        NULL,
        L"MantleTestWindow"
    };

    RegisterClass(&wc);

    HWND hWnd = CreateWindow(L"MantleTestWindow", L"Mantle Test Window", WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, NULL, NULL, hInst, NULL);

    ShowWindow(hWnd, SW_SHOW);

    return hWnd;
}

class ImageStateTransition
{
public:
    ImageStateTransition(GR_IMAGE image, GR_IMAGE_SUBRESOURCE_RANGE subResRange, GR_ENUM currentState)
    {
        assert(image != GR_NULL_HANDLE && "invalid image");
        m_trans.image = image;
        m_trans.subresourceRange = subResRange;
        m_trans.oldState = currentState;
    }

    void submit(GR_CMD_BUFFER cmdBuffer, GR_ENUM newState)
    {
        if (m_trans.oldState == newState)
            return;

        m_trans.newState = newState;
        grCmdPrepareImages(cmdBuffer, 1, &m_trans);
        m_trans.oldState = m_trans.newState;
    }

private:
    GR_IMAGE_STATE_TRANSITION m_trans;
};

struct FrameBufferInfo
{
    GR_IMAGE backBuffer;
    GR_GPU_MEMORY backBufferMemory;
    GR_IMAGE_SUBRESOURCE_RANGE subResourceRange;
    GR_COLOR_TARGET_VIEW view;
};

bool initGraphicsDevice(GR_DEVICE& device)
{
    GR_RESULT result;
    GR_APPLICATION_INFO appInfo = {};
    appInfo.apiVersion = GR_API_VERSION;

    // get the list of all physically present gpus supporting mantle. for simplicity the first one is used for rendering
    GR_PHYSICAL_GPU gpus[GR_MAX_PHYSICAL_GPUS] = {};
    GR_UINT gpuCount = 0;
    if (grInitAndEnumerateGpus(&appInfo, NULL, &gpuCount, gpus) != GR_SUCCESS)
    {
        return false;
    }

    static const GR_CHAR* const ppExtensions[] =
    {
        (GR_CHAR*)"GR_WSI_WINDOWS"
    };

    // check first if all needed extensions are supported
    bool extensionsSupported = true;
    for (int i = 0; i < _countof(ppExtensions) && extensionsSupported; ++i)
    {
        extensionsSupported &= grGetExtensionSupport(gpus[0], ppExtensions[i]) == GR_SUCCESS;
    }

    if (!extensionsSupported)
        return false;

    // create the device and request a single queue. this is should be save since a universal queue is
    // always provided. if other queues are used (i.e. async compute) the available queues should be queried first
    GR_DEVICE_QUEUE_CREATE_INFO queueInfo = {};
    queueInfo.queueCount = GR_QUEUE_UNIVERSAL;
    queueInfo.queueCount = 1;

    GR_DEVICE_CREATE_INFO deviceInfo = {};
    deviceInfo.queueRecordCount = 1;
    deviceInfo.pRequestedQueues = &queueInfo;
    deviceInfo.extensionCount = 1;
    deviceInfo.ppEnabledExtensionNames = ppExtensions;
#if defined (DEBUG) || defined (_DEBUG)
    deviceInfo.maxValidationLevel = GR_VALIDATION_LEVEL_4;
    deviceInfo.flags |= GR_DEVICE_CREATE_VALIDATION;
#else
    deviceInfo.maxValidationLevel = GR_VALIDATION_LEVEL_0;
#endif

    device = GR_NULL_HANDLE;
    result = grCreateDevice(gpus[0], &deviceInfo, &device);
    
    return (result == GR_SUCCESS);
}

void initGlobalResources(GR_DEVICE device, HWND hWnd, GR_QUEUE& renderQueue, FrameBufferInfo& frameBufferInfo)
{
    // create the actual image object and allocate memory 
    GR_WSI_WIN_PRESENTABLE_IMAGE_CREATE_INFO backBufferInfo;
    ::ZeroMemory(&backBufferInfo, sizeof(backBufferInfo));
    backBufferInfo.extent.width = 800;
    backBufferInfo.extent.height = 600;
    backBufferInfo.format.channelFormat = GR_CH_FMT_R8G8B8A8;
    backBufferInfo.format.numericFormat = GR_NUM_FMT_SRGB;
    backBufferInfo.display = GR_NULL_HANDLE;
    backBufferInfo.usage = GR_IMAGE_USAGE_COLOR_TARGET;
    CHECKED_CALL(grWsiWinCreatePresentableImage(device, &backBufferInfo, &frameBufferInfo.backBuffer, &frameBufferInfo.backBufferMemory));

    // create color target view
    GR_COLOR_TARGET_VIEW_CREATE_INFO backbufferViewInfo;
    ::ZeroMemory(&backbufferViewInfo, sizeof(backbufferViewInfo));
    backbufferViewInfo.format = backBufferInfo.format;
    backbufferViewInfo.image = frameBufferInfo.backBuffer;
    backbufferViewInfo.arraySize = 1;
    CHECKED_CALL(grCreateColorTargetView(device, &backbufferViewInfo, &frameBufferInfo.view));

    // create subresource range for operations on the data
    ::ZeroMemory(&frameBufferInfo.subResourceRange, sizeof(GR_IMAGE_SUBRESOURCE_RANGE));
    frameBufferInfo.subResourceRange.aspect = GR_IMAGE_ASPECT_COLOR;
    frameBufferInfo.subResourceRange.arraySize = 1;
    frameBufferInfo.subResourceRange.mipLevels = 1;

    // create render queues
    CHECKED_CALL(grGetDeviceQueue(device, GR_QUEUE_UNIVERSAL, 0, &renderQueue));
}
void syncWithGPU(GR_DEVICE device, GR_FENCE fence)
{
    // stall until the command buffer execution has been completed... a better solution is to get a new command buffer out of a pool (etc...)
    if (grGetFenceStatus(fence) == GR_NOT_READY)
    {
        do {} while (grWaitForFences(device, 1, &fence, GR_TRUE, 1.0f) != GR_SUCCESS);
    }
}

int main()
{
    HWND hWnd = createWindow();

    GR_DEVICE device;
    if (!initGraphicsDevice(device))
    {
        printf("cannot initialize the graphics device\n");
        return -1;
    }

    GR_QUEUE mainQueue;
    FrameBufferInfo frameBufferInfo;
    initGlobalResources(device, hWnd, mainQueue, frameBufferInfo);

    // create a new command buffer, for this example a single one is sufficient
    GR_CMD_BUFFER_CREATE_INFO cmdBufferInfo;
    cmdBufferInfo.queueType = GR_QUEUE_UNIVERSAL;
    cmdBufferInfo.flags = 0;

    GR_CMD_BUFFER cmdBuffer;
    CHECKED_CALL(grCreateCommandBuffer(device, &cmdBufferInfo, &cmdBuffer));

    // create fence to sync with the command buffer execution
    GR_FENCE_CREATE_INFO fenceInfo = {0};

    GR_FENCE fence;
    CHECKED_CALL(grCreateFence(device, &fenceInfo, &fence));

    ImageStateTransition transition(frameBufferInfo.backBuffer, 
        frameBufferInfo.subResourceRange,
        GR_IMAGE_STATE_UNINITIALIZED);

    GR_FLOAT clearColors[][3] =
    {
        {1, 0, 0},
        {0, 1, 0},
        {0, 0, 1}
    };

    int colorIndex = 0;
    
    DWORD time = GetTickCount();

    bool exit = false;
    while (!exit)
    {
        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                exit = true;
                break;
            }

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        DWORD t = GetTickCount();
        if (t - time > 5000.0f)
        {
            time = t;
            colorIndex = (colorIndex + 1) % _countof(clearColors);
        }

        // synchronize with command buffer execution
        syncWithGPU(device, fence);

        // record command buffer
        CHECKED_CALL(grBeginCommandBuffer(cmdBuffer, 0));

        // clear color, image needs to be in 'clear' state
        transition.submit(cmdBuffer, GR_IMAGE_STATE_CLEAR);
        grCmdClearColorImage(cmdBuffer, frameBufferInfo.backBuffer, clearColors[colorIndex], 1, &frameBufferInfo.subResourceRange);

        // make backbuffer ready for present
        transition.submit(cmdBuffer, GR_WSI_WIN_IMAGE_STATE_PRESENT_WINDOWED);

        CHECKED_CALL(grEndCommandBuffer(cmdBuffer));

        // submit the command buffer to the queue to let the gpu process it
        GR_MEMORY_REF memRef;
        memRef.mem = frameBufferInfo.backBufferMemory;
        memRef.flags = 0;
        CHECKED_CALL(grQueueSubmit(mainQueue, 1, &cmdBuffer, 1, &memRef, fence));

        // present backbuffer
        GR_WSI_WIN_PRESENT_INFO presentInfo;
        presentInfo.hWndDest = hWnd;
        presentInfo.srcImage = frameBufferInfo.backBuffer;
        presentInfo.flags = 0;
        presentInfo.presentMode = GR_WSI_WIN_PRESENT_MODE_WINDOWED;
        presentInfo.presentInterval = 0;

        CHECKED_CALL(grWsiWinQueuePresent(mainQueue, &presentInfo));
    }

    // sync with all command queues
    grDeviceWaitIdle(device);

    // destroy all created resources
    grDestroyObject(frameBufferInfo.view);
    grDestroyObject(cmdBuffer);
    grDestroyDevice(device);
}


Edit: mehr Kommentare + eine spannende Clearcolor-Animation :)
@D13_Dreinig

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »David_pb« (25.03.2015, 13:27)


David_pb

Community-Fossil

  • »David_pb« ist der Autor dieses Themas

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

20

26.03.2015, 14:54

Microsoft scheint die DX12 Dokumentation (draft) jetzt wohl öffentlich gemacht zu haben. Link im ersten Post.
@D13_Dreinig

Werbeanzeige