Baldur’s Gate 3 DirectX 11 or Vulkan: Which is better to use

Introduction:

Baldur’s Gate 3, an immersive role-playing game, provides players with a richly detailed world to explore. To ensure optimal gaming performance and visual fidelity, developers Larian Studios opted for either DirectX 11 or Vulkan as their graphics API. While both APIs offer various features and benefits, the choice between them can significantly impact the use of queries. In this analysis, we will compare and contrast DirectX 11 and Vulkan queries in Baldur’s Gate 3 to help users make informed decisions.

DirectX 11 Queries:

  1. Overview:
    DirectX 11, a direct graphics API developed by Microsoft, has been a popular choice for game developers due to its flexibility and ease of use. In the context of queries, DirectX 11 supports various types such as Indexed, Instanced, and Render Queries.

  2. Example: A simple example of a DirectX 11 query would be an indexed query used to determine if a specific vertex array element is within the bounds of a sphere.

    The query looks like this:

    ID3D11Query pQuery;
    D3D11_INDEXED_QUERY_DESC descQuery;
    HRESULT hr pDevice->CreateIndexedQuery(D3D11_DIMENSION_2D, 0, sizeof(float)
    3, D3D11_QUERY_TYPE_OCCLUSION, &descQuery, &pQuery, NULL);
    if (SUCCEEDED(hr)) {
    // Set the index and sphere data
    pContext->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R16G16_TYPELESS, 0);
    pContext->OMSetDepthStencilState(pDepthStencilState, NULL, 0xFF);

    // Begin the query
    hr pContext->OMSetBlendState(NULL, NULL, 0.f, D3BLEND_ONE, D3BLEND_ZERO, D3BLEND_ONE, D3BLEND_ZERO, D3BLEND_ONE, 0);
    pContext->UpdateSubresource(pIndexBuffer, 0, NULL, &indexData, sizeof(uint16_t) indexCount, 0);
    hr pContext->IASetVertexBuffers(0, 1, &vertexBuffer, sizeof(float)
    vertexStride, NULL);
    pContext->DrawIndexedInstanced(indexCount, 1, 0, 0, 0);
    D3D11_GPU_QUERY_DATA queryData;
    hr pQuery->GetData(0, sizeof(queryData), &queryData, NULL, NULL);
    if (SUCCEEDED(hr)) {
    // Handle the result based on the data returned
    }
    }

Summary: DirectX 11 queries offer a simple and efficient way to perform various tasks such as indexed, instances, and render queries.

However, they can be less performant compared to Vulkan queries due to their reliance on the CPU for scheduling and executing queries.

Vulkan Queries:

1. Overview:
Vulkan, an open-source graphics API developed by Khronos Group, offers more control over the GPU compared to DirectX 11. In terms of queries, Vulkan provides similar functionality but with greater flexibility and potential for better performance.

2. Example: A simple example of a Vulkan query would be an instance query used to determine if a specific instance in a transform array is within the bounds of a sphere.

The query looks like this:

// Allocate memory for the query data and create the descriptor
VkQueryPoolCreateInfo queryPoolCreateInfo {};
queryPoolCreateInfo.sType VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
queryPoolCreateInfo.pNext NULL;
queryPoolCreateInfo.queryBufferCount 1;
queryPoolCreateInfo.pQueryBuffers &queryBuffer;
queryPoolCreateInfo.flags 0;

VkResult result vkCreateQueryPool(device, &queryPoolCreateInfo, NULL, &queryPool);

// Record a command buffer to write the transform data into the query buffer and read back the results
VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.pNext NULL;
beginInfo.flags 0;

result vkBeginCommandBuffer(commandBuffer, &beginInfo);

//

Write the transform data into the query buffer

VkBufferStoredImageData bufferData {0};
bufferData.imageSubresource.aspectMask VK_IMAGE_ASPECT_COLOR_BIT;
bufferData.imageSubresource.baseArrayLayer 0;
bufferData.imageSubresource.layerCount 1;
result vkCmdUpdateBuffer(commandBuffer, transformBuffer, 0, sizeof(transform), &transform, 0);

// Begin the query
VkQueryCommandBufferBeginInfo queryBufferBeginInfo {};
queryBufferBeginInfo.sType VK_STRUCTURE_TYPE_QUERY_COMMAND_BUFFER_BEGIN_INFO;
queryBufferBeginInfo.pNext NULL;
queryBufferBeginInfo.queryType VK_QUERY_TYPE_OCCLUSION;
queryBufferBeginInfo.pQueryData &queryData;
result vkCmdBeginQuery(commandBuffer, queryPool, 0, &queryBufferBeginInfo);

//

Draw the instances and end the command buffer

VkDrawCommandBufferInfo drawInfo {};
drawInfo.sType VK_STRUCTURE_TYPE_DRAW_COMMANDS_INFO;
drawInfo.pNext NULL;
drawInfo.buffer vertexBuffer;
drawInfo.imageView swapChainImageView;
drawInfo.vertexOffset 0;
drawInfo.vertexCount instanceCount * 3;
vkCmdDrawCommandBuffers(commandBuffer, 1, &drawInfo);
vkEndCommandBuffer(commandBuffer);

// Read back the query results
VkQueryPoolData queryPoolData {};
result vkGetQueryPoolResults(device, queryPool, 0, sizeof(queryData), NULL, &queryPoolData, sizeof(queryData));

3. Summary: Vulkan queries offer more control over the GPU and can potentially provide better performance compared to DirectX 11 queries due to their ability to schedule and execute queries directly on the GPU.

Concluding Remarks:


DirectX 11 and Vulkan queries serve similar purposes but offer varying levels of flexibility, control, and potential performance improvements in Baldur’s Gate 3. Users seeking optimal performance may find Vulkan queries more appealing due to their direct access to the GPU, while those looking for simplicity might prefer DirectX 11 queries. Ultimately, the choice between the two depends on individual preferences and gaming requirements.

End of Analysis: We hope this comparative analysis has provided valuable insights into the use of DirectX 11 and Vulkan queries in Baldur’s Gate 3. If you have any further questions or require additional clarification, please feel free to ask.