1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[dxvk] Implemented constant state objects

This commit is contained in:
Philip Rebohle 2017-11-20 13:21:27 +01:00
parent 745466652c
commit ae0c186f26
15 changed files with 504 additions and 53 deletions

View File

@ -109,6 +109,18 @@ namespace dxvk {
return m_buffer;
}
VkBuffer bufferHandle() const {
return m_buffer->handle();
}
size_t bufferOffset() const {
return m_offset;
}
size_t bufferRange() const {
return m_length;
}
VkDescriptorBufferInfo descriptorInfo() const {
VkDescriptorBufferInfo info;
info.buffer = m_buffer->handle();

View File

@ -119,6 +119,15 @@ namespace dxvk {
}
void DxvkCommandList::cmdBindIndexBuffer(
VkBuffer buffer,
VkDeviceSize offset,
VkIndexType indexType) {
m_vkd->vkCmdBindIndexBuffer(m_buffer,
buffer, offset, indexType);
}
void DxvkCommandList::cmdBindPipeline(
VkPipelineBindPoint pipelineBindPoint,
VkPipeline pipeline) {

View File

@ -82,6 +82,11 @@ namespace dxvk {
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) final;
void cmdBindIndexBuffer(
VkBuffer buffer,
VkDeviceSize offset,
VkIndexType indexType) final;
void cmdBindPipeline(
VkPipelineBindPoint pipelineBindPoint,
VkPipeline pipeline) final;

View File

@ -76,7 +76,7 @@ namespace dxvk {
if (m_vkd->vkCreateComputePipelines(m_vkd->device(),
VK_NULL_HANDLE, 1, &info, nullptr, &m_pipeline) != VK_SUCCESS) {
this->destroyObjects();
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compipe pipeline");
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compile pipeline");
}
}

View File

@ -0,0 +1,137 @@
#include "dxvk_constant_state.h"
namespace dxvk {
DxvkInputAssemblyState::DxvkInputAssemblyState(
VkPrimitiveTopology primitiveTopology,
VkBool32 primitiveRestart) {
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.topology = primitiveTopology;
m_info.primitiveRestartEnable = primitiveRestart;
}
DxvkRasterizerState::DxvkRasterizerState(
VkBool32 enableDepthClamp,
VkBool32 enableDiscard,
VkPolygonMode polygonMode,
VkCullModeFlags cullMode,
VkFrontFace frontFace,
VkBool32 depthBiasEnable,
float depthBiasConstant,
float depthBiasClamp,
float depthBiasSlope,
float lineWidth) {
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.depthClampEnable = enableDepthClamp;
m_info.rasterizerDiscardEnable= enableDiscard;
m_info.polygonMode = polygonMode;
m_info.cullMode = cullMode;
m_info.frontFace = frontFace;
m_info.depthBiasEnable = depthBiasEnable;
m_info.depthBiasConstantFactor= depthBiasConstant;
m_info.depthBiasClamp = depthBiasClamp;
m_info.depthBiasSlopeFactor = depthBiasSlope;
m_info.lineWidth = lineWidth;
}
DxvkMultisampleState::DxvkMultisampleState(
VkSampleCountFlagBits sampleCount,
uint32_t sampleMask,
VkBool32 enableAlphaToCoverage,
VkBool32 enableAlphaToOne,
VkBool32 enableSampleShading,
float minSampleShading) {
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.rasterizationSamples = sampleCount;
m_info.sampleShadingEnable = enableSampleShading;
m_info.minSampleShading = minSampleShading;
m_info.pSampleMask = &m_mask;
m_info.alphaToCoverageEnable = enableAlphaToCoverage;
m_info.alphaToOneEnable = enableAlphaToOne;
m_mask = sampleMask;
}
DxvkDepthStencilState::DxvkDepthStencilState(
VkBool32 enableDepthTest,
VkBool32 enableDepthWrite,
VkBool32 enableDepthBounds,
VkBool32 enableStencilTest,
VkCompareOp depthCompareOp,
VkStencilOpState stencilOpFront,
VkStencilOpState stencilOpBack,
float depthBoundsMin,
float depthBoundsMax) {
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.depthTestEnable = enableDepthTest;
m_info.depthWriteEnable = enableDepthWrite;
m_info.depthCompareOp = depthCompareOp;
m_info.depthBoundsTestEnable = enableDepthBounds;
m_info.stencilTestEnable = enableStencilTest;
m_info.front = stencilOpFront;
m_info.back = stencilOpBack;
m_info.minDepthBounds = depthBoundsMin;
m_info.maxDepthBounds = depthBoundsMax;
}
DxvkBlendState::DxvkBlendState(
VkBool32 enableLogicOp,
VkLogicOp logicOp,
uint32_t attachmentCount,
const VkPipelineColorBlendAttachmentState* attachmentState) {
m_attachments.resize(attachmentCount);
for (uint32_t i = 0; i < attachmentCount; i++)
m_attachments.at(i) = attachmentState[i];
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.logicOpEnable = enableLogicOp;
m_info.logicOp = logicOp;
m_info.attachmentCount = m_attachments.size();
m_info.pAttachments = m_attachments.data();
for (uint32_t i = 0; i < 4; i++)
m_info.blendConstants[i] = 0.0f;
}
DxvkInputLayout::DxvkInputLayout(
uint32_t attributeCount,
const VkVertexInputAttributeDescription* attributeInfo,
uint32_t bindingCount,
const VkVertexInputBindingDescription* bindingInfo) {
// Copy vertex attribute info to a persistent array
m_attributes.resize(attributeCount);
for (uint32_t i = 0; i < attributeCount; i++)
m_attributes.at(i) = attributeInfo[i];
// Copy vertex binding info to a persistent array
m_bindings.resize(bindingCount);
for (uint32_t i = 0; i < bindingCount; i++)
m_bindings.at(i) = bindingInfo[i];
// Create info structure referencing those arrays
m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
m_info.pNext = nullptr;
m_info.flags = 0;
m_info.vertexBindingDescriptionCount = m_bindings.size();
m_info.pVertexBindingDescriptions = m_bindings.data();
m_info.vertexAttributeDescriptionCount = m_attributes.size();
m_info.pVertexAttributeDescriptions = m_attributes.data();
}
}

View File

@ -0,0 +1,202 @@
#pragma once
#include "dxvk_buffer.h"
#include "dxvk_framebuffer.h"
#include "dxvk_limits.h"
#include "dxvk_resource.h"
#include "dxvk_shader.h"
namespace dxvk {
/**
* \brief Input assembly state
*
* Stores the primitive topology and
* whether or not primitive restart
* is enabled.
*/
class DxvkInputAssemblyState : public RcObject {
public:
DxvkInputAssemblyState(
VkPrimitiveTopology primitiveTopology,
VkBool32 primitiveRestart);
const VkPipelineInputAssemblyStateCreateInfo& info() const {
return m_info;
}
private:
VkPipelineInputAssemblyStateCreateInfo m_info;
};
/**
* \brief Rasterizer state
*
* Stores the operating mode of the
* rasterizer, including the depth bias.
*/
class DxvkRasterizerState : public RcObject {
public:
DxvkRasterizerState(
VkBool32 enableDepthClamp,
VkBool32 enableDiscard,
VkPolygonMode polygonMode,
VkCullModeFlags cullMode,
VkFrontFace frontFace,
VkBool32 depthBiasEnable,
float depthBiasConstant,
float depthBiasClamp,
float depthBiasSlope,
float lineWidth);
const VkPipelineRasterizationStateCreateInfo& info() const {
return m_info;
}
private:
VkPipelineRasterizationStateCreateInfo m_info;
};
/**
* \brief Multisample state
*
* Defines details on how to handle
* multisampling, including the alpha
* coverage mode.
*/
class DxvkMultisampleState : public RcObject {
public:
DxvkMultisampleState(
VkSampleCountFlagBits sampleCount,
uint32_t sampleMask,
VkBool32 enableAlphaToCoverage,
VkBool32 enableAlphaToOne,
VkBool32 enableSampleShading,
float minSampleShading);
const VkPipelineMultisampleStateCreateInfo& info() const {
return m_info;
}
private:
VkPipelineMultisampleStateCreateInfo m_info;
uint32_t m_mask;
};
/**
* \brief Depth-stencil state
*
* Defines the depth test and stencil
* operations for the graphics pipeline.
*/
class DxvkDepthStencilState : public RcObject {
public:
DxvkDepthStencilState(
VkBool32 enableDepthTest,
VkBool32 enableDepthWrite,
VkBool32 enableDepthBounds,
VkBool32 enableStencilTest,
VkCompareOp depthCompareOp,
VkStencilOpState stencilOpFront,
VkStencilOpState stencilOpBack,
float depthBoundsMin,
float depthBoundsMax);
const VkPipelineDepthStencilStateCreateInfo& info() const {
return m_info;
}
private:
VkPipelineDepthStencilStateCreateInfo m_info;
};
/**
* \brief Blend state
*
* Stores the color blend state for each
* available framebuffer attachment.
*/
class DxvkBlendState : public RcObject {
public:
DxvkBlendState(
VkBool32 enableLogicOp,
VkLogicOp logicOp,
uint32_t attachmentCount,
const VkPipelineColorBlendAttachmentState* attachmentState);
const VkPipelineColorBlendStateCreateInfo& info() const {
return m_info;
}
private:
std::vector<VkPipelineColorBlendAttachmentState> m_attachments;
VkPipelineColorBlendStateCreateInfo m_info;
};
/**
* \brief Input layout
*
* Stores the attributes and vertex buffer binding
* descriptions that the vertex shader will take
* its input values from.
*/
class DxvkInputLayout : public RcObject {
public:
DxvkInputLayout(
uint32_t attributeCount,
const VkVertexInputAttributeDescription* attributeInfo,
uint32_t bindingCount,
const VkVertexInputBindingDescription* bindingInfo);
const VkPipelineVertexInputStateCreateInfo& info() const {
return m_info;
}
private:
std::vector<VkVertexInputAttributeDescription> m_attributes;
std::vector<VkVertexInputBindingDescription> m_bindings;
VkPipelineVertexInputStateCreateInfo m_info;
};
struct DxvkConstantStateObjects {
Rc<DxvkInputAssemblyState> inputAssembly;
Rc<DxvkInputLayout> inputLayout;
Rc<DxvkRasterizerState> rasterizerState;
Rc<DxvkMultisampleState> multisampleState;
Rc<DxvkDepthStencilState> depthStencilState;
Rc<DxvkBlendState> blendState;
};
}

View File

@ -34,6 +34,7 @@ namespace dxvk {
m_state.flags.set(
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyDynamicState,
DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::GpDirtyIndexBuffer,
DxvkContextFlag::GpDirtyVertexBuffers,
@ -63,6 +64,15 @@ namespace dxvk {
}
void DxvkContext::bindIndexBuffer(
const DxvkBufferBinding& buffer) {
if (m_state.vi.indexBuffer != buffer) {
m_state.vi.indexBuffer = buffer;
m_state.flags.set(DxvkContextFlag::GpDirtyIndexBuffer);
}
}
void DxvkContext::bindShader(
VkShaderStageFlagBits stage,
const Rc<DxvkShader>& shader) {
@ -89,6 +99,16 @@ namespace dxvk {
}
void DxvkContext::bindVertexBuffer(
uint32_t binding,
const DxvkBufferBinding& buffer) {
if (m_state.vi.vertexBuffers.at(binding) != buffer) {
m_state.vi.vertexBuffers.at(binding) = buffer;
m_state.flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
}
}
void DxvkContext::clearRenderTarget(
const VkClearAttachment& attachment,
const VkClearRect& clearArea) {
@ -174,7 +194,7 @@ namespace dxvk {
m_state.flags.clr(DxvkContextFlag::GpDirtyPipelineState);
DxvkGraphicsPipelineStateInfo gpState;
gpState.renderPass = m_state.om.framebuffer->renderPass();
// TODO fill state object
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
m_state.activeGraphicsPipeline->getPipelineHandle(gpState));
@ -182,9 +202,44 @@ namespace dxvk {
}
void DxvkContext::bindDynamicState() {
if (m_state.flags.test(DxvkContextFlag::GpDirtyDynamicState)) {
m_state.flags.clr(DxvkContextFlag::GpDirtyDynamicState);
// TODO implement
}
}
void DxvkContext::bindIndexBuffer() {
if (m_state.flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) {
m_state.flags.clr(DxvkContextFlag::GpDirtyIndexBuffer);
m_cmd->cmdBindIndexBuffer(
m_state.vi.indexBuffer.bufferHandle(),
m_state.vi.indexBuffer.bufferOffset(),
VK_INDEX_TYPE_UINT32);
m_cmd->trackResource(
m_state.vi.indexBuffer.resource());
}
}
void DxvkContext::bindVertexBuffers() {
if (m_state.flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) {
m_state.flags.clr(DxvkContextFlag::GpDirtyVertexBuffers);
// TODO implement
}
}
void DxvkContext::flushGraphicsState() {
this->renderPassBegin();
this->bindGraphicsPipeline();
this->bindDynamicState();
this->bindIndexBuffer();
this->bindVertexBuffers();
}

View File

@ -55,6 +55,13 @@ namespace dxvk {
void bindFramebuffer(
const Rc<DxvkFramebuffer>& fb);
/**
* \brief Binds index buffer
* \param [in] buffer New index buffer
*/
void bindIndexBuffer(
const DxvkBufferBinding& buffer);
/**
* \brief Sets shader for a given shader stage
*
@ -69,6 +76,16 @@ namespace dxvk {
VkShaderStageFlagBits stage,
const Rc<DxvkShader>& shader);
/**
* \brief Binds vertex buffer
*
* \param [in] binding Vertex buffer binding
* \param [in] buffer New vertex buffer
*/
void bindVertexBuffer(
uint32_t binding,
const DxvkBufferBinding& buffer);
/**
* \brief Clears an active render target
*
@ -118,10 +135,12 @@ namespace dxvk {
DxvkContextState m_state;
void renderPassBegin();
void renderPassEnd();
void bindGraphicsPipeline();
void bindDynamicState();
void bindIndexBuffer();
void bindVertexBuffers();
void flushGraphicsState();

View File

@ -2,6 +2,7 @@
#include "dxvk_buffer.h"
#include "dxvk_compute.h"
#include "dxvk_constant_state.h"
#include "dxvk_framebuffer.h"
#include "dxvk_graphics.h"
#include "dxvk_image.h"
@ -21,6 +22,7 @@ namespace dxvk {
GpRenderPassBound, ///< Render pass is currently bound
GpDirtyPipeline, ///< Graphics pipeline binding are out of date
GpDirtyPipelineState, ///< Graphics pipeline state (blending etc.) is dirty
GpDirtyDynamicState, ///< Dynamic state needs to be reapplied
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
@ -32,58 +34,25 @@ namespace dxvk {
using DxvkContextFlags = Flags<DxvkContextFlag>;
/**
* \brief Shader state
*
* Stores the active shader and resources
* for a single shader stage. All stages
* support the same types of resources.
*/
struct DxvkShaderStageState {
Rc<DxvkShader> shader;
};
/**
* \brief Input assembly state
*
* Stores the primitive topology
* and the vertex input layout.
*/
struct DxvkInputAssemblyState {
VkPrimitiveTopology primitiveTopology;
VkBool32 primitiveRestart;
uint32_t numVertexBindings = 0;
uint32_t numVertexAttributes = 0;
std::array<VkVertexInputBindingDescription,
DxvkLimits::MaxNumVertexBuffers> vertexBindings;
std::array<VkVertexInputAttributeDescription,
DxvkLimits::MaxNumVertexBuffers> vertexAttributes;
};
/**
* \brief Vertex input state
*
* Stores the currently bound index
* buffer and vertex buffers.
*/
struct DxvkVertexInputState {
Rc<DxvkBuffer> indexBuffer;
std::array<Rc<DxvkBuffer>,
DxvkLimits::MaxNumVertexBuffers> vertexBuffers;
DxvkBufferBinding indexBuffer;
std::array<DxvkBufferBinding,
DxvkLimits::MaxNumVertexBindings> vertexBuffers;
};
struct DxvkViewportState {
uint32_t viewportCount = 0;
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports;
std::array<VkRect2D, DxvkLimits::MaxNumViewports> scissorRects;
};
/**
* \brief Output merger state
*
* Stores the active framebuffer and the current
* blend state, as well as the depth stencil state.
*/
struct DxvkOutputMergerState {
Rc<DxvkFramebuffer> framebuffer;
};
@ -103,9 +72,10 @@ namespace dxvk {
DxvkShaderStageState fs;
DxvkShaderStageState cs;
DxvkInputAssemblyState ia;
DxvkVertexInputState vi;
DxvkViewportState vp;
DxvkOutputMergerState om;
DxvkConstantStateObjects co;
Rc<DxvkGraphicsPipeline> activeGraphicsPipeline;
Rc<DxvkComputePipeline> activeComputePipeline;

View File

@ -2,13 +2,34 @@
namespace dxvk {
template<typename T>
size_t hashPtr(T* ptr) {
return reinterpret_cast<size_t>(ptr);
}
size_t DxvkGraphicsPipelineStateInfo::hash() const {
// TODO implement
DxvkHashState state;
state.add(hashPtr(this->inputAssembly.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<VkRenderPass>()(this->renderPass));
state.add(viewportCount);
return state;
}
bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const {
return this->renderPass == other.renderPass;
return this->inputAssembly == other.inputAssembly
&& 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;
}

View File

@ -3,6 +3,7 @@
#include <mutex>
#include <unordered_map>
#include "dxvk_constant_state.h"
#include "dxvk_hash.h"
#include "dxvk_shader.h"
#include "dxvk_resource.h"
@ -12,10 +13,21 @@ namespace dxvk {
/**
* \brief Graphics pipeline state info
*
*
* Stores all information that is required to create
* a graphics pipeline, except the shader objects
* themselves. Also used to identify pipelines using
* the current pipeline state vector.
*/
struct DxvkGraphicsPipelineStateInfo {
VkRenderPass renderPass;
Rc<DxvkInputAssemblyState> inputAssembly;
Rc<DxvkInputLayout> inputLayout;
Rc<DxvkRasterizerState> rasterizerState;
Rc<DxvkMultisampleState> multisampleState;
Rc<DxvkDepthStencilState> depthStencilState;
Rc<DxvkBlendState> blendState;
VkRenderPass renderPass;
uint32_t viewportCount;
size_t hash() const;

View File

@ -133,7 +133,6 @@ namespace dxvk {
DxvkImageViewCreateInfo m_info;
VkImageView m_view;
};
}

View File

@ -1,11 +1,15 @@
#pragma once
#include "dxvk_include.h"
namespace dxvk {
enum DxvkLimits : size_t {
MaxNumRenderTargets = 8,
MaxNumVertexBuffers = 32,
MaxNumVertexAttributes = 32,
MaxNumVertexBindings = 32,
MaxNumOutputStreams = 4,
MaxNumViewports = 16,
};
}

View File

@ -39,6 +39,11 @@ namespace dxvk {
const VkRenderPassBeginInfo* pRenderPassBegin,
VkSubpassContents contents) = 0;
virtual void cmdBindIndexBuffer(
VkBuffer buffer,
VkDeviceSize offset,
VkIndexType indexType) = 0;
virtual void cmdBindPipeline(
VkPipelineBindPoint pipelineBindPoint,
VkPipeline pipeline) = 0;

View File

@ -4,6 +4,7 @@ dxvk_src = files([
'dxvk_buffer.cpp',
'dxvk_cmdlist.cpp',
'dxvk_compute.cpp',
'dxvk_constant_state.cpp',
'dxvk_context.cpp',
'dxvk_deferred.cpp',
'dxvk_descriptor.cpp',