[dxvk] Initial work on instance data fetch rates

Adds a pipeline flag to indicate that instanced
draw calls need to be emulated.
This commit is contained in:
Philip Rebohle 2018-02-01 20:15:25 +01:00
parent 0154d0856d
commit 14d5054893
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 68 additions and 37 deletions

View File

@ -731,17 +731,10 @@ namespace dxvk {
// set by D3D11DeviceContext::IASetVertexBuffers.
DxvkVertexBinding binding;
binding.binding = pInputElementDescs[i].InputSlot;
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) {
binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
if (pInputElementDescs[i].InstanceDataStepRate != 1) {
Logger::warn(str::format(
"D3D11Device: Unsupported instance data step rate: ",
pInputElementDescs[i].InstanceDataStepRate));
}
}
binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
? VK_VERTEX_INPUT_RATE_INSTANCE
: VK_VERTEX_INPUT_RATE_VERTEX;
// Check if the binding was already defined. If so, the
// parameters must be identical (namely, the input rate).

View File

@ -4930,6 +4930,8 @@ namespace dxvk {
m_module.setDebugName(typeId, "s_push_constant");
m_module.setDebugMemberName(typeId, PerVertex_Position, "instance_id");
// There's only ever going to be one single push constant
// block per shader, so we'll declare the variable here
uint32_t ptrTypeId = m_module.defPointerType(
typeId, spv::StorageClassPushConstant);

View File

@ -333,6 +333,17 @@ namespace dxvk {
}
void cmdPushConstants(
VkPipelineLayout layout,
VkShaderStageFlags stageFlags,
uint32_t offset,
uint32_t size,
const void* pValues) {
m_vkd->vkCmdPushConstants(m_buffer,
layout, stageFlags, offset, size, pValues);
}
void cmdResolveImage(
VkImage srcImage,
VkImageLayout srcImageLayout,

View File

@ -136,6 +136,7 @@ namespace dxvk {
*/
struct DxvkVertexBinding {
uint32_t binding;
uint32_t fetchRate;
VkVertexInputRate inputRate;
};

View File

@ -572,9 +572,16 @@ namespace dxvk {
this->commitGraphicsState();
if (m_gpActivePipeline != VK_NULL_HANDLE) {
m_cmd->cmdDraw(
vertexCount, instanceCount,
firstVertex, firstInstance);
if (!m_flags.test(DxvkContextFlag::GpEmulateInstanceFetchRate)) {
m_cmd->cmdDraw(
vertexCount, instanceCount,
firstVertex, firstInstance);
} else {
static bool errorShown = false;
if (!std::exchange(errorShown, true))
Logger::warn("Dxvk: GpEmulateInstanceFetchRate not supported for direct draws");
}
}
}
@ -588,10 +595,17 @@ namespace dxvk {
if (m_gpActivePipeline != VK_NULL_HANDLE) {
auto physicalSlice = buffer.physicalSlice();
m_cmd->cmdDrawIndirect(
physicalSlice.handle(),
physicalSlice.offset(),
count, stride);
if (!m_flags.test(DxvkContextFlag::GpEmulateInstanceFetchRate)) {
m_cmd->cmdDrawIndirect(
physicalSlice.handle(),
physicalSlice.offset(),
count, stride);
} else {
static bool errorShown = false;
if (!std::exchange(errorShown, true))
Logger::warn("Dxvk: GpEmulateInstanceFetchRate not supported for indirect draws");
}
}
}
@ -1042,6 +1056,8 @@ namespace dxvk {
m_flags.set(
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyVertexBuffers);
m_flags.clr(
DxvkContextFlag::GpEmulateInstanceFetchRate);
for (uint32_t i = 0; i < attributeCount; i++) {
m_state.gp.state.ilAttributes[i].location = attributes[i].location;
@ -1056,6 +1072,10 @@ namespace dxvk {
for (uint32_t i = 0; i < bindingCount; i++) {
m_state.gp.state.ilBindings[i].binding = bindings[i].binding;
m_state.gp.state.ilBindings[i].inputRate = bindings[i].inputRate;
m_state.vi.vertexFetchRates[bindings[i].binding] = bindings[i].fetchRate;
if (bindings[i].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE && bindings[i].fetchRate != 1)
m_flags.set(DxvkContextFlag::GpEmulateInstanceFetchRate);
}
for (uint32_t i = bindingCount; i < m_state.gp.state.ilBindingCount; i++)

View File

@ -558,12 +558,12 @@ namespace dxvk {
void updateShaderResources(
VkPipelineBindPoint bindPoint,
const Rc<DxvkPipelineLayout>& layout);
const Rc<DxvkPipelineLayout>& layout);
void updateShaderDescriptors(
VkPipelineBindPoint bindPoint,
const DxvkBindingState& bindingState,
const Rc<DxvkPipelineLayout>& layout);
const Rc<DxvkPipelineLayout>& layout);
void updateViewports();
void updateBlendConstants();

View File

@ -21,16 +21,17 @@ namespace dxvk {
* be updated.
*/
enum class DxvkContextFlag : uint64_t {
GpRenderPassBound, ///< Render pass is currently bound
GpDirtyPipeline, ///< Graphics pipeline binding is out of date
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date
GpDirtyIndexBuffer, ///< Index buffer binding are out of date
GpRenderPassBound, ///< Render pass is currently bound
GpDirtyPipeline, ///< Graphics pipeline binding is out of date
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date
GpDirtyIndexBuffer, ///< Index buffer binding are out of date
GpEmulateInstanceFetchRate, ///< The current input layout uses fetch rates != 1
CpDirtyPipeline, ///< Compute pipeline binding are out of date
CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled
CpDirtyResources, ///< Compute pipeline resource bindings are out of date
CpDirtyPipeline, ///< Compute pipeline binding are out of date
CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled
CpDirtyResources, ///< Compute pipeline resource bindings are out of date
};
using DxvkContextFlags = Flags<DxvkContextFlag>;
@ -42,23 +43,25 @@ namespace dxvk {
uint32_t bindingMask = 0;
std::array<DxvkBufferSlice,
DxvkLimits::MaxNumVertexBindings> vertexBuffers;
DxvkLimits::MaxNumVertexBindings> vertexBuffers = { };
std::array<uint32_t,
DxvkLimits::MaxNumVertexBindings> vertexStrides;
DxvkLimits::MaxNumVertexBindings> vertexStrides = { };
std::array<uint32_t,
DxvkLimits::MaxNumVertexBindings> vertexFetchRates = { };
};
struct DxvkViewportState {
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports;
std::array<VkRect2D, DxvkLimits::MaxNumViewports> scissorRects;
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports = { };
std::array<VkRect2D, DxvkLimits::MaxNumViewports> scissorRects = { };
};
struct DxvkOutputMergerState {
Rc<DxvkFramebuffer> framebuffer;
DxvkBlendConstants blendConstants;
uint32_t stencilReference;
DxvkBlendConstants blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f };
uint32_t stencilReference = 0;
};
@ -73,9 +76,9 @@ namespace dxvk {
DxvkShaderStage tes;
DxvkShaderStage gs;
DxvkShaderStage fs;
DxvkGraphicsPipelineStateInfo state;
Rc<DxvkGraphicsPipeline> pipeline;
Rc<DxvkGraphicsPipeline> pipeline;
};

View File

@ -14,6 +14,7 @@ namespace dxvk {
MaxNumActiveBindings = 128,
MaxNumQueuedCommandBuffers = 8,
MaxVertexBindingStride = 2048,
MaxPushConstantSize = 128,
};
}