Fixed D3D12 renderer not working with batching, and got rid of the vertex buffer size limit
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
diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index 24c29f7..9642b40 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -27,7 +27,6 @@
#define SDL_D3D12_NUM_BUFFERS 2
#define SDL_D3D12_NUM_VERTEX_BUFFERS 256
-#define SDL_D3D12_VERTEX_BUFFER_MAX_TRIS 2048
#define SDL_D3D12_MAX_NUM_TEXTURES 16384
#define SDL_D3D12_NUM_UPLOAD_BUFFERS 32
@@ -139,6 +138,7 @@ typedef struct
{
ID3D12Resource *resource;
D3D12_VERTEX_BUFFER_VIEW view;
+ size_t size;
} D3D12_VertexBuffer;
/* For SRV pool allocator */
@@ -189,7 +189,6 @@ typedef struct
D3D12_PipelineState *currentPipelineState;
D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS];
- ID3D12Heap *vertexBufferHeap;
D3D12_CPU_DESCRIPTOR_HANDLE nearestPixelSampler;
D3D12_CPU_DESCRIPTOR_HANDLE linearSampler;
@@ -320,7 +319,6 @@ D3D12_ReleaseAll(SDL_Renderer * renderer)
SAFE_RELEASE(data->samplerDescriptorHeap);
SAFE_RELEASE(data->swapChain);
SAFE_RELEASE(data->fence);
- SAFE_RELEASE(data->vertexBufferHeap);
for (i = 0; i < SDL_D3D12_NUM_BUFFERS; ++i) {
SAFE_RELEASE(data->commandAllocators[i]);
@@ -649,6 +647,55 @@ D3D12_CreatePipelineState(SDL_Renderer * renderer,
return &pipelineStates[data->pipelineStateCount - 1];
}
+static HRESULT
+D3D12_CreateVertexBuffer(D3D12_RenderData *data, size_t vbidx, size_t size)
+{
+ D3D12_HEAP_PROPERTIES vbufferHeapProps;
+ D3D12_RESOURCE_DESC vbufferDesc;
+ HRESULT result;
+
+ SAFE_RELEASE(data->vertexBuffers[vbidx].resource);
+
+ SDL_zero(vbufferHeapProps);
+ vbufferHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ vbufferHeapProps.CreationNodeMask = 1;
+ vbufferHeapProps.VisibleNodeMask = 1;
+
+ SDL_zero(vbufferDesc);
+ vbufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ vbufferDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+ vbufferDesc.Width = size;
+ vbufferDesc.Height = 1;
+ vbufferDesc.DepthOrArraySize = 1;
+ vbufferDesc.MipLevels = 1;
+ vbufferDesc.Format = DXGI_FORMAT_UNKNOWN;
+ vbufferDesc.SampleDesc.Count = 1;
+ vbufferDesc.SampleDesc.Quality = 0;
+ vbufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ vbufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ result = D3D_CALL(data->d3dDevice, CreateCommittedResource,
+ &vbufferHeapProps,
+ D3D12_HEAP_FLAG_NONE,
+ &vbufferDesc,
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ NULL,
+ D3D_GUID(SDL_IID_ID3D12Resource),
+ (void **) &data->vertexBuffers[vbidx].resource
+ );
+
+ if (FAILED(result)) {
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreatePlacedResource [vertex buffer]"), result);
+ return result;
+ }
+
+ data->vertexBuffers[vbidx].view.BufferLocation = D3D_CALL(data->vertexBuffers[vbidx].resource, GetGPUVirtualAddress);
+ data->vertexBuffers[vbidx].view.StrideInBytes = sizeof(VertexPositionColor);
+ data->vertexBuffers[vbidx].size = size;
+
+ return result;
+}
+
/* Create resources that depend on the device. */
static HRESULT
D3D12_CreateDeviceResources(SDL_Renderer* renderer)
@@ -665,8 +712,6 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
D3D12_COMMAND_QUEUE_DESC queueDesc;
D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc;
- D3D12_HEAP_DESC vbufferHeapDesc;
- D3D12_RESOURCE_DESC vbufferDesc;
D3D12_SAMPLER_DESC samplerDesc;
ID3D12DescriptorHeap *rootDescriptorHeaps[2];
@@ -965,49 +1010,9 @@ D3D12_CreateDeviceResources(SDL_Renderer* renderer)
}
}
- /* Create a vertex buffer heap and populate it with resources */
- SDL_zero(vbufferHeapDesc);
- vbufferHeapDesc.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT * SDL_D3D12_NUM_VERTEX_BUFFERS;
- D3D_CALL_RET(data->d3dDevice, GetCustomHeapProperties, &vbufferHeapDesc.Properties, 0, D3D12_HEAP_TYPE_UPLOAD);
- vbufferHeapDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- vbufferHeapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
- result = D3D_CALL(data->d3dDevice, CreateHeap, &vbufferHeapDesc, D3D_GUID(SDL_IID_ID3D12Heap), (void **)&data->vertexBufferHeap);
- if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreateHeap"), result);
- goto done;
- }
-
- SDL_zero(vbufferDesc);
- vbufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- vbufferDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- vbufferDesc.Width = sizeof(VertexPositionColor) * SDL_D3D12_VERTEX_BUFFER_MAX_TRIS;
- vbufferDesc.Height = 1;
- vbufferDesc.DepthOrArraySize = 1;
- vbufferDesc.MipLevels = 1;
- vbufferDesc.Format = DXGI_FORMAT_UNKNOWN;
- vbufferDesc.SampleDesc.Count = 1;
- vbufferDesc.SampleDesc.Quality = 0;
- vbufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- vbufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
-
+ /* Create default vertex buffers */
for (i = 0; i < SDL_D3D12_NUM_VERTEX_BUFFERS; ++i) {
- result = D3D_CALL(data->d3dDevice, CreatePlacedResource,
- data->vertexBufferHeap,
- i * D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT,
- &vbufferDesc,
- D3D12_RESOURCE_STATE_GENERIC_READ,
- NULL,
- D3D_GUID(SDL_IID_ID3D12Resource),
- (void **)&data->vertexBuffers[i].resource
- );
-
- if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D12Device::CreatePlacedResource [vertex buffer]"), result);
- goto done;
- }
-
- data->vertexBuffers[i].view.BufferLocation = D3D_CALL(data->vertexBuffers[i].resource, GetGPUVirtualAddress);
- data->vertexBuffers[i].view.StrideInBytes = sizeof(VertexPositionColor);
+ D3D12_CreateVertexBuffer(data, i, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
}
/* Create samplers to use when drawing textures: */
@@ -2223,9 +2228,9 @@ D3D12_UpdateVertexBuffer(SDL_Renderer *renderer,
}
}
- if (dataSizeInBytes > SDL_D3D12_VERTEX_BUFFER_MAX_TRIS * stride) {
- SDL_SetError("d3d12 renderer does not support more than %d verts in a vertex buffer", SDL_D3D12_VERTEX_BUFFER_MAX_TRIS);
- return E_FAIL;
+ /* If the existing vertex buffer isn't big enough, we need to recreate a big enough one */
+ if (dataSizeInBytes > rendererData->vertexBuffers[vbidx].size) {
+ D3D12_CreateVertexBuffer(rendererData, vbidx, dataSizeInBytes);
}
vertexBuffer = rendererData->vertexBuffers[vbidx].resource;
@@ -2578,7 +2583,7 @@ D3D12_DrawPrimitives(SDL_Renderer * renderer, D3D12_PRIMITIVE_TOPOLOGY primitive
{
D3D12_RenderData *rendererData = (D3D12_RenderData *) renderer->driverdata;
D3D_CALL(rendererData->commandList, IASetPrimitiveTopology, primitiveTopology);
- D3D_CALL(rendererData->commandList, DrawInstanced, (UINT)vertexCount, 1, 0, 0);
+ D3D_CALL(rendererData->commandList, DrawInstanced, (UINT)vertexCount, 1, (UINT)vertexStart, 0);
}
static int