[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. // set by D3D11DeviceContext::IASetVertexBuffers.
DxvkVertexBinding binding; DxvkVertexBinding binding;
binding.binding = pInputElementDescs[i].InputSlot; binding.binding = pInputElementDescs[i].InputSlot;
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; binding.fetchRate = pInputElementDescs[i].InstanceDataStepRate;
binding.inputRate = pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA
if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) { ? VK_VERTEX_INPUT_RATE_INSTANCE
binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; : VK_VERTEX_INPUT_RATE_VERTEX;
if (pInputElementDescs[i].InstanceDataStepRate != 1) {
Logger::warn(str::format(
"D3D11Device: Unsupported instance data step rate: ",
pInputElementDescs[i].InstanceDataStepRate));
}
}
// Check if the binding was already defined. If so, the // Check if the binding was already defined. If so, the
// parameters must be identical (namely, the input rate). // 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.setDebugName(typeId, "s_push_constant");
m_module.setDebugMemberName(typeId, PerVertex_Position, "instance_id"); 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( uint32_t ptrTypeId = m_module.defPointerType(
typeId, spv::StorageClassPushConstant); 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( void cmdResolveImage(
VkImage srcImage, VkImage srcImage,
VkImageLayout srcImageLayout, VkImageLayout srcImageLayout,

View File

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

View File

@ -572,9 +572,16 @@ namespace dxvk {
this->commitGraphicsState(); this->commitGraphicsState();
if (m_gpActivePipeline != VK_NULL_HANDLE) { if (m_gpActivePipeline != VK_NULL_HANDLE) {
m_cmd->cmdDraw( if (!m_flags.test(DxvkContextFlag::GpEmulateInstanceFetchRate)) {
vertexCount, instanceCount, m_cmd->cmdDraw(
firstVertex, firstInstance); 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) { if (m_gpActivePipeline != VK_NULL_HANDLE) {
auto physicalSlice = buffer.physicalSlice(); auto physicalSlice = buffer.physicalSlice();
m_cmd->cmdDrawIndirect( if (!m_flags.test(DxvkContextFlag::GpEmulateInstanceFetchRate)) {
physicalSlice.handle(), m_cmd->cmdDrawIndirect(
physicalSlice.offset(), physicalSlice.handle(),
count, stride); 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( m_flags.set(
DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyVertexBuffers); DxvkContextFlag::GpDirtyVertexBuffers);
m_flags.clr(
DxvkContextFlag::GpEmulateInstanceFetchRate);
for (uint32_t i = 0; i < attributeCount; i++) { for (uint32_t i = 0; i < attributeCount; i++) {
m_state.gp.state.ilAttributes[i].location = attributes[i].location; m_state.gp.state.ilAttributes[i].location = attributes[i].location;
@ -1056,6 +1072,10 @@ namespace dxvk {
for (uint32_t i = 0; i < bindingCount; i++) { for (uint32_t i = 0; i < bindingCount; i++) {
m_state.gp.state.ilBindings[i].binding = bindings[i].binding; m_state.gp.state.ilBindings[i].binding = bindings[i].binding;
m_state.gp.state.ilBindings[i].inputRate = bindings[i].inputRate; 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++) for (uint32_t i = bindingCount; i < m_state.gp.state.ilBindingCount; i++)

View File

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

View File

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

View File

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