diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 5a197030..df6f6a02 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -561,7 +561,8 @@ namespace dxvk { } m_context->bindVertexBuffer( - StartSlot + i, dxvkBinding); + StartSlot + i, dxvkBinding, + binding.stride); } } diff --git a/src/dxvk/dxvk_constant_state.cpp b/src/dxvk/dxvk_constant_state.cpp index 16e95c41..8d166b63 100644 --- a/src/dxvk/dxvk_constant_state.cpp +++ b/src/dxvk/dxvk_constant_state.cpp @@ -1,3 +1,5 @@ +#include + #include "dxvk_constant_state.h" namespace dxvk { diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index ddffeccf..60ca9082 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -6,7 +6,7 @@ namespace dxvk { DxvkContext::DxvkContext(const Rc& device) : m_device(device) { - + Logger::info(str::format(sizeof(DxvkGraphicsPipelineStateInfo))); } @@ -183,11 +183,17 @@ namespace dxvk { void DxvkContext::bindVertexBuffer( uint32_t binding, - const DxvkBufferBinding& buffer) { + const DxvkBufferBinding& buffer, + uint32_t stride) { if (m_state.vi.vertexBuffers.at(binding) != buffer) { m_state.vi.vertexBuffers.at(binding) = buffer; m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); } + + if (m_state.vi.vertexStrides.at(binding) != stride) { + m_state.vi.vertexStrides.at(binding) = stride; + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + } } @@ -499,15 +505,65 @@ namespace dxvk { } DxvkGraphicsPipelineStateInfo gpState; - gpState.inputAssemblyState = m_state.co.inputAssemblyState; - gpState.inputLayout = m_state.co.inputLayout; - gpState.rasterizerState = m_state.co.rasterizerState; - gpState.multisampleState = m_state.co.multisampleState; - gpState.depthStencilState = m_state.co.depthStencilState; - gpState.blendState = m_state.co.blendState; - gpState.renderPass = m_state.om.framebuffer->renderPass(); - gpState.viewportCount = m_state.vp.viewportCount; - // TODO add vertex buffer strides + + const auto& ia = m_state.co.inputAssemblyState->info(); + gpState.iaPrimitiveTopology = ia.topology; + gpState.iaPrimitiveRestart = ia.primitiveRestartEnable; + + const auto& il = m_state.co.inputLayout->info(); + gpState.ilAttributeCount = il.vertexAttributeDescriptionCount; + gpState.ilBindingCount = il.vertexBindingDescriptionCount; + + for (uint32_t i = 0; i < gpState.ilAttributeCount; i++) + gpState.ilAttributes[i] = il.pVertexAttributeDescriptions[i]; + + for (uint32_t i = 0; i < gpState.ilBindingCount; i++) { + gpState.ilBindings[i] = il.pVertexBindingDescriptions[i]; + gpState.ilBindings[i].stride = m_state.vi.vertexStrides.at(i); + } + + const auto& rs = m_state.co.rasterizerState->info(); + gpState.rsEnableDepthClamp = rs.depthClampEnable; + gpState.rsEnableDiscard = rs.rasterizerDiscardEnable; + gpState.rsPolygonMode = rs.polygonMode; + gpState.rsCullMode = rs.cullMode; + gpState.rsFrontFace = rs.frontFace; + gpState.rsDepthBiasEnable = rs.depthBiasEnable; + gpState.rsDepthBiasConstant = rs.depthBiasConstantFactor; + gpState.rsDepthBiasClamp = rs.depthBiasClamp; + gpState.rsDepthBiasSlope = rs.depthBiasSlopeFactor; + gpState.rsViewportCount = m_state.vp.viewportCount; + + // TODO implement multisampling support properly + const auto& ms = m_state.co.multisampleState->info(); + gpState.msSampleCount = VK_SAMPLE_COUNT_1_BIT; + gpState.msSampleMask = *ms.pSampleMask; + gpState.msEnableAlphaToCoverage = ms.alphaToCoverageEnable; + gpState.msEnableAlphaToOne = ms.alphaToOneEnable; + gpState.msEnableSampleShading = ms.sampleShadingEnable; + gpState.msMinSampleShading = ms.minSampleShading; + + const auto& ds = m_state.co.depthStencilState->info(); + gpState.dsEnableDepthTest = ds.depthTestEnable; + gpState.dsEnableDepthWrite = ds.depthWriteEnable; + gpState.dsEnableDepthBounds = ds.depthBoundsTestEnable; + gpState.dsEnableStencilTest = ds.stencilTestEnable; + gpState.dsDepthCompareOp = ds.depthCompareOp; + gpState.dsStencilOpFront = ds.front; + gpState.dsStencilOpBack = ds.back; + gpState.dsDepthBoundsMin = ds.minDepthBounds; + gpState.dsDepthBoundsMax = ds.maxDepthBounds; + + const auto& om = m_state.co.blendState->info(); + gpState.omEnableLogicOp = om.logicOpEnable; + gpState.omLogicOp = om.logicOp; + gpState.omRenderPass = m_state.om.framebuffer->renderPass(); + + const auto& rt = m_state.om.framebuffer->renderTargets(); + for (uint32_t i = 0; i < DxvkLimits::MaxNumRenderTargets; i++) { + if (rt.getColorTarget(i) != nullptr) + gpState.omBlendAttachments[i] = om.pAttachments[i]; + } m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, m_state.gp.pipeline->getPipelineHandle(gpState)); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 9d01d86c..7dac9faf 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -140,7 +140,8 @@ namespace dxvk { */ void bindVertexBuffer( uint32_t binding, - const DxvkBufferBinding& buffer); + const DxvkBufferBinding& buffer, + uint32_t stride); /** * \brief Clears subresources of a color image diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 90c3b54f..e493c535 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -42,6 +42,8 @@ namespace dxvk { std::array vertexBuffers; + std::array vertexStrides; }; diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 0029f063..5e69da58 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -1,40 +1,38 @@ +#include + #include "dxvk_graphics.h" namespace dxvk { - template - size_t hashPtr(T* ptr) { - return reinterpret_cast(ptr); - } - - size_t DxvkGraphicsPipelineStateInfo::hash() const { - DxvkHashState state; - state.add(hashPtr(this->inputAssemblyState.ptr())); - state.add(hashPtr(this->inputLayout.ptr())); - state.add(hashPtr(this->rasterizerState.ptr())); - state.add(hashPtr(this->multisampleState.ptr())); - state.add(hashPtr(this->depthStencilState.ptr())); - state.add(hashPtr(this->blendState.ptr())); - state.add(std::hash()(this->renderPass)); - state.add(viewportCount); - return state; + DxvkGraphicsPipelineStateInfo::DxvkGraphicsPipelineStateInfo() { + std::memset(this, 0, sizeof(DxvkGraphicsPipelineStateInfo)); } - bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const { - return this->inputAssemblyState == other.inputAssemblyState - && this->inputLayout == other.inputLayout - && this->rasterizerState == other.rasterizerState - && this->multisampleState == other.multisampleState - && this->depthStencilState == other.depthStencilState - && this->blendState == other.blendState - && this->renderPass == other.renderPass - && this->viewportCount == other.viewportCount; + DxvkGraphicsPipelineStateInfo::DxvkGraphicsPipelineStateInfo( + const DxvkGraphicsPipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(DxvkGraphicsPipelineStateInfo)); } - bool DxvkGraphicsPipelineStateInfo::operator != (const DxvkGraphicsPipelineStateInfo& other) const { - return !this->operator == (other); + DxvkGraphicsPipelineStateInfo& DxvkGraphicsPipelineStateInfo::operator = ( + const DxvkGraphicsPipelineStateInfo& other) { + std::memcpy(this, &other, sizeof(DxvkGraphicsPipelineStateInfo)); + return *this; + } + + + size_t DxvkGraphicsPipelineStateHash::operator () ( + const DxvkGraphicsPipelineStateInfo& state) const { + // TODO implement hash + return 0; + } + + + size_t DxvkGraphicsPipelineStateEq::operator () ( + const DxvkGraphicsPipelineStateInfo& a, + const DxvkGraphicsPipelineStateInfo& b) const { + return std::memcmp(&a, &b, sizeof(DxvkGraphicsPipelineStateInfo)) == 0; } @@ -101,42 +99,110 @@ namespace dxvk { if (m_gs != nullptr) stages.push_back(m_gs->stageInfo()); if (m_fs != nullptr) stages.push_back(m_fs->stageInfo()); - VkPipelineViewportStateCreateInfo vpInfo; - vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vpInfo.pNext = nullptr; - vpInfo.flags = 0; - vpInfo.viewportCount = state.viewportCount; - vpInfo.pViewports = nullptr; - vpInfo.scissorCount = state.viewportCount; - vpInfo.pScissors = nullptr; + VkPipelineVertexInputStateCreateInfo viInfo; + viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + viInfo.pNext = nullptr; + viInfo.flags = 0; + viInfo.vertexBindingDescriptionCount = state.ilBindingCount; + viInfo.pVertexBindingDescriptions = state.ilBindings; + viInfo.vertexAttributeDescriptionCount = state.ilAttributeCount; + viInfo.pVertexAttributeDescriptions = state.ilAttributes; - VkPipelineDynamicStateCreateInfo dsInfo; - dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dsInfo.pNext = nullptr; - dsInfo.flags = 0; - dsInfo.dynamicStateCount = dynamicStates.size(); - dsInfo.pDynamicStates = dynamicStates.data(); + VkPipelineInputAssemblyStateCreateInfo iaInfo; + iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + iaInfo.pNext = nullptr; + iaInfo.flags = 0; + iaInfo.topology = state.iaPrimitiveTopology; + iaInfo.primitiveRestartEnable = state.iaPrimitiveRestart; + + VkPipelineViewportStateCreateInfo vpInfo; + vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpInfo.pNext = nullptr; + vpInfo.flags = 0; + vpInfo.viewportCount = state.rsViewportCount; + vpInfo.pViewports = nullptr; + vpInfo.scissorCount = state.rsViewportCount; + vpInfo.pScissors = nullptr; + + VkPipelineRasterizationStateCreateInfo rsInfo; + rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rsInfo.pNext = nullptr; + rsInfo.flags = 0; + rsInfo.depthClampEnable = state.rsEnableDepthClamp; + rsInfo.rasterizerDiscardEnable= state.rsEnableDiscard; + rsInfo.polygonMode = state.rsPolygonMode; + rsInfo.cullMode = state.rsCullMode; + rsInfo.frontFace = state.rsFrontFace; + rsInfo.depthBiasEnable = state.rsDepthBiasEnable; + rsInfo.depthBiasConstantFactor= state.rsDepthBiasConstant; + rsInfo.depthBiasClamp = state.rsDepthBiasClamp; + rsInfo.depthBiasSlopeFactor = state.rsDepthBiasSlope; + rsInfo.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo msInfo; + msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + msInfo.pNext = nullptr; + msInfo.flags = 0; + msInfo.rasterizationSamples = state.msSampleCount; + msInfo.sampleShadingEnable = state.msEnableSampleShading; + msInfo.minSampleShading = state.msMinSampleShading; + msInfo.pSampleMask = &state.msSampleMask; + msInfo.alphaToCoverageEnable = state.msEnableAlphaToCoverage; + msInfo.alphaToOneEnable = state.msEnableAlphaToOne; + + VkPipelineDepthStencilStateCreateInfo dsInfo; + dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + dsInfo.pNext = nullptr; + dsInfo.flags = 0; + dsInfo.depthTestEnable = state.dsEnableDepthTest; + dsInfo.depthWriteEnable = state.dsEnableDepthWrite; + dsInfo.depthCompareOp = state.dsDepthCompareOp; + dsInfo.depthBoundsTestEnable = state.dsEnableDepthBounds; + dsInfo.stencilTestEnable = state.dsEnableStencilTest; + dsInfo.front = state.dsStencilOpFront; + dsInfo.back = state.dsStencilOpBack; + dsInfo.minDepthBounds = state.dsDepthBoundsMin; + dsInfo.maxDepthBounds = state.dsDepthBoundsMax; + + VkPipelineColorBlendStateCreateInfo cbInfo; + cbInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + cbInfo.pNext = nullptr; + cbInfo.flags = 0; + cbInfo.logicOpEnable = state.omEnableLogicOp; + cbInfo.logicOp = state.omLogicOp; + cbInfo.attachmentCount = DxvkLimits::MaxNumRenderTargets; + cbInfo.pAttachments = state.omBlendAttachments; + + for (uint32_t i = 0; i < 4; i++) + cbInfo.blendConstants[i] = 0.0f; + + VkPipelineDynamicStateCreateInfo dyInfo; + dyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dyInfo.pNext = nullptr; + dyInfo.flags = 0; + dyInfo.dynamicStateCount = dynamicStates.size(); + dyInfo.pDynamicStates = dynamicStates.data(); VkGraphicsPipelineCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - info.stageCount = stages.size(); - info.pStages = stages.data(); - info.pVertexInputState = &state.inputLayout->info(); - info.pInputAssemblyState = &state.inputAssemblyState->info(); - info.pTessellationState = nullptr; // TODO implement - info.pViewportState = &vpInfo; - info.pRasterizationState = &state.rasterizerState->info(); - info.pMultisampleState = &state.multisampleState->info(); - info.pDepthStencilState = &state.depthStencilState->info(); - info.pColorBlendState = &state.blendState->info(); - info.pDynamicState = &dsInfo; - info.layout = m_layout->pipelineLayout(); - info.renderPass = state.renderPass; - info.subpass = 0; - info.basePipelineHandle = VK_NULL_HANDLE; - info.basePipelineIndex = 0; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stages.size(); + info.pStages = stages.data(); + info.pVertexInputState = &viInfo; + info.pInputAssemblyState = &iaInfo; + info.pTessellationState = nullptr; // TODO implement + info.pViewportState = &vpInfo; + info.pRasterizationState = &rsInfo; + info.pMultisampleState = &msInfo; + info.pDepthStencilState = &dsInfo; + info.pColorBlendState = &cbInfo; + info.pDynamicState = &dyInfo; + info.layout = m_layout->pipelineLayout(); + info.renderPass = state.omRenderPass; + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; // TODO use this + info.basePipelineIndex = 0; VkPipeline pipeline = VK_NULL_HANDLE; if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 83d5d611..e77d0b0a 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -20,20 +20,65 @@ namespace dxvk { * the current pipeline state vector. */ struct DxvkGraphicsPipelineStateInfo { - Rc inputAssemblyState; - Rc inputLayout; - Rc rasterizerState; - Rc multisampleState; - Rc depthStencilState; - Rc blendState; + DxvkGraphicsPipelineStateInfo(); + DxvkGraphicsPipelineStateInfo( + const DxvkGraphicsPipelineStateInfo& other); - VkRenderPass renderPass; - uint32_t viewportCount; + DxvkGraphicsPipelineStateInfo& operator = ( + const DxvkGraphicsPipelineStateInfo& other); - size_t hash() const; + VkPrimitiveTopology iaPrimitiveTopology; + VkBool32 iaPrimitiveRestart; - bool operator == (const DxvkGraphicsPipelineStateInfo& other) const; - bool operator != (const DxvkGraphicsPipelineStateInfo& other) const; + uint32_t ilAttributeCount; + uint32_t ilBindingCount; + VkVertexInputAttributeDescription ilAttributes[DxvkLimits::MaxNumVertexAttributes]; + VkVertexInputBindingDescription ilBindings[DxvkLimits::MaxNumVertexBindings]; + + VkBool32 rsEnableDepthClamp; + VkBool32 rsEnableDiscard; + VkPolygonMode rsPolygonMode; + VkCullModeFlags rsCullMode; + VkFrontFace rsFrontFace; + VkBool32 rsDepthBiasEnable; + float rsDepthBiasConstant; + float rsDepthBiasClamp; + float rsDepthBiasSlope; + uint32_t rsViewportCount; + + VkSampleCountFlagBits msSampleCount; + uint32_t msSampleMask; + VkBool32 msEnableAlphaToCoverage; + VkBool32 msEnableAlphaToOne; + VkBool32 msEnableSampleShading; + float msMinSampleShading; + + VkBool32 dsEnableDepthTest; + VkBool32 dsEnableDepthWrite; + VkBool32 dsEnableDepthBounds; + VkBool32 dsEnableStencilTest; + VkCompareOp dsDepthCompareOp; + VkStencilOpState dsStencilOpFront; + VkStencilOpState dsStencilOpBack; + float dsDepthBoundsMin; + float dsDepthBoundsMax; + + VkBool32 omEnableLogicOp; + VkLogicOp omLogicOp; + VkRenderPass omRenderPass; + VkPipelineColorBlendAttachmentState omBlendAttachments[DxvkLimits::MaxNumRenderTargets]; + }; + + + struct DxvkGraphicsPipelineStateHash { + size_t operator () (const DxvkGraphicsPipelineStateInfo& state) const; + }; + + + struct DxvkGraphicsPipelineStateEq { + size_t operator () ( + const DxvkGraphicsPipelineStateInfo& a, + const DxvkGraphicsPipelineStateInfo& b) const; }; @@ -91,7 +136,9 @@ namespace dxvk { std::unordered_map< DxvkGraphicsPipelineStateInfo, - VkPipeline, DxvkHash> m_pipelines; + VkPipeline, + DxvkGraphicsPipelineStateHash, + DxvkGraphicsPipelineStateEq> m_pipelines; VkPipeline compilePipeline( const DxvkGraphicsPipelineStateInfo& state) const;