13

The main gain would be that it would be easier to divide CPU tasks into multiple threads, without having to solve all the difficult issues with accessing the graphics API. Normally you either would have to make the context current (which might have bad performance implications) or provide a queue and call the graphics api in a single thread. I don't think ...


12

D3D12 has 4 separate kinds of command lists: direct, bundle, compute, and copy. Vulkan has similar concepts, but they happen in a different way. Command buffers are allocated from command pools. And command pools are directly associated with a queue family. And command buffers allocated from a pool can only be submitted to the queue family for which the ...


10

In DX12, a descriptor is a small record, basically a pointer, that tells the GPU where to find some data such as a constant buffer. Since each object is going to have its own constant buffer data with its own particular transforms, lighting/material properties, etc., each object also has to end up with a separate set of descriptors to point to its individual ...


9

There's a lot of work needed on the CPU to set up a frame for the GPU, and a good chunk of that work is inside the graphics driver. Prior to DX12 / Vulkan, that graphics driver work was essentially forced to be single-threaded by the design of the API. The hope is that DX12 / Vulkan lift that restriction, allowing driver work to be performed in parallel on ...


7

In DX12, there is no implicit driver-implemented SLI as there was in DX11. Instead, multiple GPUs are exposed to the application as separate "nodes" within a single DX12 device, and each VRAM resource lives on a single node, specified at creation time. There is no implicit mirroring of resources to both GPUs as in DX11 SLI. So, the game engine or ...


6

It's very different between the Khronos standards (including Vulkan) and DirectX. In DirectX, Microsoft implements the API, but they publish to GPU vendors a HAL API. There's actually two HALs: one that runs in kernel-mode, to communicate with the card directly; and one that runs in user-space, to do other tasks (like manage memory, set up data structures, ...


5

Modern GPUs generally have a single frontend section that processes an entirely linear stream of commands from the CPU. Whether this is a natural hardware design or if it simply evolved out of the days when there was a single CPU core generating commands for the GPU is debatable, but it's the reality for now. So if you generate a single linear stream of ...


5

Vector has a few different semantics from static arrays. For one it's a struct containing a pointer a capacity and a length (at the very least). That means that sizeof will not reflect how much data is actually stored in there (that only works on static arrays). If you need to get the size in bytes of the data then you need const UINT vertexBufferSize = ...


5

TL;DR: There's some room for optimization in Vulkan drivers, but not nearly to the degree that there is in GL / DX11 drivers. how much do drivers affect performance? It depends a great deal on how the application is written and the hardware. Specifically it depends on whether you're using features where there are large opportunities for optimization on ...


4

In your first example, the call to WaitForSingleObject blocks the thread. This puts it into a waiting state, which takes it off the run queue and allows other threads to run on this CPU core. If no threads can run, the CPU will idle. When the fenceEvent completes, it wakes up this thread. Your proposed replacement is called a spinlock. The thread keeps ...


3

The problem looks like it's in this line: d3dDevice->CreateConstantBufferView(cbvDesc, cbvHandle1); The first parameter should be &cbvDesc[1]. As it is now, you're setting up two copies of cbvDesc[0]. Also, it looks like you've reversed the second and third arguments to the cbvHandle1 constructor: the second argument should be the offset (1) and ...


3

There are two general ways the graphics driver can implement Map(). One way is to set up a virtual memory mapping that makes the resource's actual memory (could be system memory or GPU memory) visible as part of the application's address space. If it does happen to be GPU memory, any writes you do would typically be buffered up and sent across the PCIe bus ...


3

You have to use the appropriate register type for the resource: b registers for constant buffers, t for textures, and u for UAVs. AFAIK, it is not possible to bind a UAV to a texture slot, or otherwise mismatch registers and resources. However, a resource can have multiple views, so it is possible to have a resource bound as a UAV in one shader and as a ...


2

You're trying to map all three UAVs to the same descriptor slot (slot 0). ranges_madhu[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE); ranges_madhu[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE); ranges_madhu[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, ...


2

If I understand you correctly, you've added a new compute shader. In DX12, you'll need at least one separate PSO for each shader, since the shader code is part of the PSO.


2

You don't. These objects typically work with CPU memory, not device memory. And to the extent that they involve device memory, such allocations tend to be rare and/or fixed in size (a queue may have a small spot of device memory that the hardware queue reads commands from or something, but even that is implementation-dependent). Vulkan allows you to give ...


2

You should be able to use RWTexture3D. The hlsl documentation page about RWTexture2D also has sample code that you might find useful.


1

So, I figured it out. While UAV will be necessary when I start manipulating data in Compute Shaders, for the time being, SRV works fine provided the resource is read-only from the fragment shader. The two big problems were Creating an ImageTexture that was receiving the data. Note that the data copy was occurring just fine, but the texture was never used ...


1

First you may want to take a look at the doc. Map basically allows you to retrieve a CPU pointer of a GPU resource. It performs a few operations on the background so the data is up to date. Depending on the type of resource you are mapping, you can perform different tasks like reading data or copying it. As far as I know, Map will only allocate an address ...


1

Ok, so I made little example of how to do this. Short version You need to allocate additional buffer with heap type D3D12_HEAP_TYPE_READBACK and resource state set to D3D12_RESOURCE_STATE_COPY_DEST. Then create command list with type D3D12_COMMAND_LIST_TYPE_COPY. After dispatch compute shader use fence to check if buffer is ready, then copy from this ...


1

Ship your application with a benchmarking sequence testing the actual platform. (Possible answer for many questions I guess...) I suspect the performance is highly dependent on how you use the hardware. Since the hardware is unlikely to somehow instrument your application backwards, telling you what to do, I´d go with whatever looks good in your design. "...


Only top voted, non community-wiki answers of a minimum length are eligible