[dxvk] Restructured state tracker again

This commit is contained in:
Philip Rebohle 2017-11-17 19:49:44 +01:00
parent b367f6af55
commit a84e2eabc2
7 changed files with 172 additions and 516 deletions

View File

@ -37,98 +37,19 @@ namespace dxvk {
virtual ~DxbcCodeGen();
/**
* \brief Declares temporary registers
* \param [in] n Number of temp registers
*/
void dclTemps(uint32_t n);
/**
* \brief Declares an interface variable
*
* \param [in] regType Register type
* \param [in] regId Interface register index
* \param [in] regDim Array dimension of interface variable
* \param [in] regMask Component mask for this declaration
* \param [in] sv System value to map to the given components
*/
virtual void dclInterfaceVar(
DxbcOperandType regType,
uint32_t regId,
uint32_t regDim,
DxbcComponentMask regMask,
DxbcSystemValue sv) = 0;
/**
* \brief Defines 32-bit constant
*
* The constant will be declared as a 32-bit
* unsigned integer. Cast the resulting value
* to the required type.
* \param [in] v Constant value
* \returns The constant value ID
*/
DxbcValue defConstScalar(uint32_t v);
/**
* \brief Defines 32-bit constant vector
*
* Defines a four-component vector of 32-bit
* unsigned integer values. Cast the resulting
* value to the required type as needed.
* \param [in] x First vector component
* \param [in] y Second vector component
* \param [in] z Third vector component
* \param [in] w Fourth vector component
* \returns The constant value ID
*/
DxbcValue defConstVector(
uint32_t x, uint32_t y,
uint32_t z, uint32_t w);
/**
* \brief Returns from function
*/
void fnReturn();
/**
* \brief Retrieves temporary register pointer
*
* Provides access to a temporary register.
* \param [in] regId Register index
* \returns Register pointer
*/
DxbcPointer ptrTempReg(
uint32_t regId);
/**
* \brief Pointer to an interface variable
*
* Provides access to an interface variable.
* \param [in] regType Register type
* \param [in] regId Register index
* \returns Register pointer
*/
virtual DxbcPointer ptrInterfaceVar(
DxbcOperandType regType,
uint32_t regId) = 0;
/**
* \brief Pointer to an interface variable
*
* Provides access to an indexed interface variable.
* Some shader types may have indexed input or output
* variables that can be accesswed via an array index.
* \param [in] regType Register type
* \param [in] regId Register index
* \param [in] index Array index
* \returns Register pointer
*/
virtual DxbcPointer ptrInterfaceVarIndexed(
DxbcOperandType regType,
uint32_t regId,
const DxbcValue& index) = 0;
DxbcValue opAbs(
const DxbcValue& src);
@ -146,99 +67,50 @@ namespace dxvk {
DxbcValue opSaturate(
const DxbcValue& src);
/**
* \brief Casts register value to another type
*
* Type cast that does not change the bit pattern
* of the value. This is required as DXBC values
* are not statically typed, but SPIR-V is.
* \param [in] src Source value
* \param [in] type Destination type
* \returns Resulting register value
*/
DxbcValue regCast(
const DxbcValue& src,
const DxbcValueType& type);
/**
* \brief Extracts vector components
*
* Extracts the given set of components.
* \param [in] src Source vector
* \param [in] mask Component mask
* \returns Resulting register value
*/
DxbcValue regExtract(
const DxbcValue& src,
DxbcComponentMask mask);
/**
* \brief Swizzles a vector register
*
* Swizzles the vector and extracts
* the given set of vector components.
* \param [in] src Source vector to swizzle
* \param [in] swizzle The component swizzle
* \param [in] mask Components to extract
* \returns Resulting register value
*/
DxbcValue regSwizzle(
const DxbcValue& src,
const DxbcComponentSwizzle& swizzle,
DxbcComponentMask mask);
/**
* \brief Writes to parts of a vector register
*
* Note that the source value must have the same
* number of components as the write mask.
* \param [in] dst Destination value ID
* \param [in] src Source value ID
* \param [in] mask Write mask
* \returns New destination value ID
*/
DxbcValue regInsert(
const DxbcValue& dst,
const DxbcValue& src,
DxbcComponentMask mask);
/**
* \brief Loads register
*
* \param [in] ptr Register pointer
* \returns The register value ID
*/
DxbcValue regLoad(
const DxbcPointer& ptr);
/**
* \brief Stores register
*
* \param [in] ptr Register pointer
* \param [in] val Value ID to store
* \param [in] mask Write mask
*/
void regStore(
const DxbcPointer& ptr,
const DxbcValue& val,
DxbcComponentMask mask);
/**
* \brief Finalizes shader
*
* Depending on the shader stage, this may generate
* additional code to set up input variables, output
* variables, and execute shader phases.
* \returns DXVK shader module
*/
virtual void dclInterfaceVar(
DxbcOperandType regType,
uint32_t regId,
uint32_t regDim,
DxbcComponentMask regMask,
DxbcSystemValue sv) = 0;
virtual DxbcPointer ptrInterfaceVar(
DxbcOperandType regType,
uint32_t regId) = 0;
virtual DxbcPointer ptrInterfaceVarIndexed(
DxbcOperandType regType,
uint32_t regId,
const DxbcValue& index) = 0;
virtual Rc<DxvkShader> finalize() = 0;
/**
* \brief Creates code generator for a given program type
*
* \param [in] version Program version
* \returns The code generator
*/
static Rc<DxbcCodeGen> create(
const DxbcProgramVersion& version);

View File

@ -21,38 +21,34 @@ namespace dxvk {
void DxvkContext::beginRecording(
const Rc<DxvkRecorder>& recorder) {
TRACE(this, recorder);
m_cmd = recorder;
m_cmd->beginRecording();
// Make sure that we apply the current context state
// to the command buffer when recording draw commands.
m_state.g.flags.clr(
DxvkGraphicsPipelineBit::RenderPassBound);
m_state.g.flags.set(
DxvkGraphicsPipelineBit::PipelineDirty,
DxvkGraphicsPipelineBit::PipelineStateDirty,
DxvkGraphicsPipelineBit::DirtyResources,
DxvkGraphicsPipelineBit::DirtyVertexBuffers,
DxvkGraphicsPipelineBit::DirtyIndexBuffer);
// The current state of the internal command buffer is
// undefined, so we have to bind and set up everything
// before any draw or dispatch command is recorded.
m_state.flags.clr(
DxvkContextFlag::GpRenderPassBound);
m_state.c.flags.set(
DxvkComputePipelineBit::PipelineDirty,
DxvkComputePipelineBit::DirtyResources);
m_state.flags.set(
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::GpDirtyIndexBuffers,
DxvkContextFlag::GpDirtyVertexBuffers,
DxvkContextFlag::CpDirtyPipeline,
DxvkContextFlag::CpDirtyResources);
}
bool DxvkContext::endRecording() {
void DxvkContext::endRecording() {
TRACE(this);
// Any currently active render pass must be
// ended before finalizing the command buffer.
if (m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
this->endRenderPass();
this->renderPassEnd();
// Finalize the command list
m_cmd->endRecording();
m_cmd = nullptr;
return true;
}
@ -60,12 +56,9 @@ namespace dxvk {
const Rc<DxvkFramebuffer>& fb) {
TRACE(this, fb);
if (m_state.g.fb != fb) {
m_state.g.fb = fb;
if (m_state.g.flags.test(
DxvkGraphicsPipelineBit::RenderPassBound))
this->endRenderPass();
if (m_state.om.framebuffer != fb) {
m_state.om.framebuffer = fb;
this->renderPassEnd();
}
}
@ -75,34 +68,23 @@ namespace dxvk {
const Rc<DxvkShader>& shader) {
TRACE(this, stage, shader);
DxvkShaderState* state = this->getShaderState(stage);
DxvkShaderStageState* stageState = this->getShaderStage(stage);
if (state->shader != shader) {
state->shader = shader;
this->setPipelineDirty(stage);
}
}
void DxvkContext::bindStorageBuffer(
VkShaderStageFlagBits stage,
uint32_t slot,
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize length) {
TRACE(this, stage, slot);
DxvkBufferBinding binding(buffer, offset, length);
DxvkShaderState* state = this->getShaderState(stage);
// TODO investigate whether it is worth checking whether
// the shader actually uses the resource. However, if the
// application is not completely retarded, always setting
// the 'resources dirty' flag should be the best option.
if (state->boundStorageBuffers.at(slot) != binding) {
state->boundStorageBuffers.at(slot) = binding;
this->setResourcesDirty(stage);
m_cmd->trackResource(binding.resource());
if (stageState->shader != shader) {
stageState->shader = shader;
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
m_state.flags.set(
DxvkContextFlag::CpDirtyPipeline,
DxvkContextFlag::CpDirtyResources);
} else {
m_state.flags.set(
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::GpDirtyVertexBuffers,
DxvkContextFlag::GpDirtyIndexBuffers);
}
}
}
@ -110,28 +92,18 @@ namespace dxvk {
void DxvkContext::clearRenderTarget(
const VkClearAttachment& attachment,
const VkClearRect& clearArea) {
this->flushGraphicsState();
TRACE(this);
// We only need the framebuffer to be bound. Flushing the
// entire pipeline state is not required and might actually
// cause problems if the current pipeline state is invalid.
this->renderPassBegin();
m_cmd->cmdClearAttachments(
1, &attachment, 1, &clearArea);
}
void DxvkContext::dispatch(
uint32_t wgCountX,
uint32_t wgCountY,
uint32_t wgCountZ) {
TRACE(this, wgCountX, wgCountY, wgCountZ);
this->endRenderPass();
this->flushComputeState();
m_cmd->cmdDispatch(
wgCountX, wgCountY, wgCountZ);
// TODO resource barriers
}
void DxvkContext::draw(
uint32_t vertexCount,
uint32_t instanceCount,
@ -139,11 +111,6 @@ namespace dxvk {
uint32_t firstInstance) {
TRACE(this, vertexCount, instanceCount,
firstVertex, firstInstance);
this->flushGraphicsState();
m_cmd->cmdDraw(
vertexCount, instanceCount,
firstVertex, firstInstance);
}
@ -155,162 +122,86 @@ namespace dxvk {
uint32_t firstInstance) {
TRACE(this, indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
this->flushGraphicsState();
m_cmd->cmdDrawIndexed(
indexCount, instanceCount,
firstIndex, vertexOffset,
firstInstance);
}
void DxvkContext::flushComputeState() {
if (m_state.c.flags.test(DxvkComputePipelineBit::PipelineDirty)) {
m_state.c.pipeline = m_pipeMgr->getComputePipeline(m_state.c.cs.shader);
void DxvkContext::renderPassBegin() {
if (!m_state.flags.test(DxvkContextFlag::GpRenderPassBound)
&& (m_state.om.framebuffer != nullptr)) {
m_state.flags.set(DxvkContextFlag::GpRenderPassBound);
if (m_state.c.pipeline != nullptr) {
m_cmd->cmdBindPipeline(
VK_PIPELINE_BIND_POINT_COMPUTE,
m_state.c.pipeline->getPipelineHandle());
}
const DxvkFramebufferSize fbSize
= m_state.om.framebuffer->size();
VkRect2D renderArea;
renderArea.offset = VkOffset2D { 0, 0 };
renderArea.extent = VkExtent2D { fbSize.width, fbSize.height };
VkRenderPassBeginInfo info;
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.pNext = nullptr;
info.renderPass = m_state.om.framebuffer->renderPass();
info.framebuffer = m_state.om.framebuffer->handle();
info.renderArea = renderArea;
info.clearValueCount = 0;
info.pClearValues = nullptr;
m_cmd->cmdBeginRenderPass(&info,
VK_SUBPASS_CONTENTS_INLINE);
}
}
void DxvkContext::renderPassEnd() {
if (m_state.flags.test(DxvkContextFlag::GpRenderPassBound)) {
m_state.flags.clr(DxvkContextFlag::GpRenderPassBound);
m_cmd->cmdEndRenderPass();
}
}
void DxvkContext::bindGraphicsPipeline() {
if (m_state.flags.test(DxvkContextFlag::GpDirtyPipeline)) {
m_state.flags.clr(DxvkContextFlag::GpDirtyPipeline);
m_state.activeGraphicsPipeline = m_pipeMgr->getGraphicsPipeline(
m_state.vs.shader, m_state.tcs.shader, m_state.tes.shader,
m_state.gs.shader, m_state.fs.shader);
}
if (m_state.c.flags.test(DxvkComputePipelineBit::DirtyResources)
&& m_state.c.pipeline != nullptr) {
std::vector<DxvkResourceBinding> bindings;
this->addResourceBindingInfo(bindings, m_state.c.cs);
if (m_state.flags.test(DxvkContextFlag::GpDirtyPipelineState)
&& m_state.activeGraphicsPipeline != nullptr) {
m_state.flags.clr(DxvkContextFlag::GpDirtyPipelineState);
m_cmd->bindShaderResources(
VK_PIPELINE_BIND_POINT_COMPUTE,
m_state.c.pipeline->pipelineLayout(),
m_state.c.pipeline->descriptorSetLayout(),
bindings.size(), bindings.data());
DxvkGraphicsPipelineStateInfo gpState;
gpState.renderPass = m_state.om.framebuffer->renderPass();
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
m_state.activeGraphicsPipeline->getPipelineHandle(gpState));
}
m_state.c.flags.clr(
DxvkComputePipelineBit::PipelineDirty,
DxvkComputePipelineBit::DirtyResources);
}
void DxvkContext::flushGraphicsState() {
if (!m_state.g.flags.test(DxvkGraphicsPipelineBit::RenderPassBound))
this->beginRenderPass();
this->renderPassBegin();
this->bindGraphicsPipeline();
}
void DxvkContext::beginRenderPass() {
TRACE(this);
DxvkFramebufferSize fbsize
= m_state.g.fb->size();
VkRenderPassBeginInfo info;
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.pNext = nullptr;
info.renderPass = m_state.g.fb->renderPass();
info.framebuffer = m_state.g.fb->handle();
info.renderArea = VkRect2D { { 0, 0 }, { fbsize.width, fbsize.height } };
info.clearValueCount = 0;
info.pClearValues = nullptr;
m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE);
m_state.g.flags.set(DxvkGraphicsPipelineBit::RenderPassBound);
}
void DxvkContext::endRenderPass() {
TRACE(this);
m_cmd->cmdEndRenderPass();
m_state.g.flags.clr(DxvkGraphicsPipelineBit::RenderPassBound);
}
void DxvkContext::setPipelineDirty(VkShaderStageFlagBits stage) {
if (stage == VK_SHADER_STAGE_COMPUTE_BIT) {
m_state.c.flags.set(
DxvkComputePipelineBit::PipelineDirty,
DxvkComputePipelineBit::DirtyResources);
} else {
m_state.g.flags.set(
DxvkGraphicsPipelineBit::PipelineDirty,
DxvkGraphicsPipelineBit::DirtyResources);
}
}
void DxvkContext::setResourcesDirty(VkShaderStageFlagBits stage) {
if (stage == VK_SHADER_STAGE_COMPUTE_BIT)
m_state.c.flags.set(DxvkComputePipelineBit::DirtyResources);
else
m_state.g.flags.set(DxvkGraphicsPipelineBit::DirtyResources);
}
DxvkShaderState* DxvkContext::getShaderState(VkShaderStageFlagBits stage) {
DxvkShaderStageState* DxvkContext::getShaderStage(VkShaderStageFlagBits stage) {
switch (stage) {
case VK_SHADER_STAGE_VERTEX_BIT:
return &m_state.g.vs;
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
return &m_state.g.tcs;
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
return &m_state.g.tes;
case VK_SHADER_STAGE_VERTEX_BIT: return &m_state.vs;
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: return &m_state.tcs;
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: return &m_state.tes;
case VK_SHADER_STAGE_GEOMETRY_BIT: return &m_state.gs;
case VK_SHADER_STAGE_FRAGMENT_BIT: return &m_state.fs;
case VK_SHADER_STAGE_COMPUTE_BIT: return &m_state.cs;
case VK_SHADER_STAGE_GEOMETRY_BIT:
return &m_state.g.gs;
case VK_SHADER_STAGE_FRAGMENT_BIT:
return &m_state.g.fs;
case VK_SHADER_STAGE_COMPUTE_BIT:
return &m_state.c.cs;
default:
return nullptr;
throw DxvkError(str::format(
"DxvkContext::getShaderStage: Invalid stage bit: ",
static_cast<uint32_t>(stage)));
}
}
uint32_t DxvkContext::addResourceBindingInfo(
std::vector<DxvkResourceBinding>& bindings,
const DxvkShaderState& stageInfo) const {
const uint32_t slotCount = stageInfo.shader->slotCount();
for (uint32_t i = 0; i < slotCount; i++) {
DxvkResourceSlot slot = stageInfo.shader->slot(i);
DxvkResourceBinding binding;
switch (slot.type) {
case DxvkResourceType::ImageSampler:
binding.type = VK_DESCRIPTOR_TYPE_SAMPLER;
break;
case DxvkResourceType::SampledImage:
binding.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
break;
case DxvkResourceType::StorageImage:
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
break;
case DxvkResourceType::UniformBuffer:
binding.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
binding.buffer = stageInfo.boundUniformBuffers.at(slot.slot).descriptorInfo();
break;
case DxvkResourceType::StorageBuffer:
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
binding.buffer = stageInfo.boundStorageBuffers.at(slot.slot).descriptorInfo();
break;
}
bindings.push_back(binding);
}
return slotCount;
}
}

View File

@ -43,17 +43,10 @@ namespace dxvk {
* The command list can then be submitted to
* the device.
*
* The return value of this method can be used to
* determine whether the command list needs to be
* submitted. In case the command list is empty,
* \c false will be returned and it shall not be
* submitted to the device.
*
* This will not change any context state
* other than the active command list.
* \returns \c true if any commands were recorded
*/
bool endRecording();
void endRecording();
/**
* \brief Sets framebuffer
@ -76,20 +69,6 @@ namespace dxvk {
VkShaderStageFlagBits stage,
const Rc<DxvkShader>& shader);
/**
* \brief Binds a storage buffer
*
* \param [in] stage Shader stage for this binding
* \param [in] slot Binding slot index
* \param [in] buffer Buffer binding info
*/
void bindStorageBuffer(
VkShaderStageFlagBits stage,
uint32_t slot,
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize length);
/**
* \brief Clears an active render target
*
@ -100,18 +79,6 @@ namespace dxvk {
const VkClearAttachment& attachment,
const VkClearRect& clearArea);
/**
* \brief Dispatches compute operations
*
* \param [in] wgCountX Number of X work groups
* \param [in] wgCountY Number of Y work groups
* \param [in] wgCountZ Number of Z work groups
*/
void dispatch(
uint32_t wgCountX,
uint32_t wgCountY,
uint32_t wgCountZ);
/**
* \brief Draws primitive without using an index buffer
*
@ -150,25 +117,16 @@ namespace dxvk {
Rc<DxvkRecorder> m_cmd;
DxvkContextState m_state;
void flushComputeState();
void renderPassBegin();
void renderPassEnd();
void bindGraphicsPipeline();
void flushGraphicsState();
void beginRenderPass();
void endRenderPass();
void setPipelineDirty(VkShaderStageFlagBits stage);
void setResourcesDirty(VkShaderStageFlagBits stage);
void shaderResourceBarriers(
DxvkBarrierSet& barriers,
VkShaderStageFlagBits stage);
DxvkShaderState* getShaderState(
VkShaderStageFlagBits stage);
uint32_t addResourceBindingInfo(
std::vector<DxvkResourceBinding>& bindings,
const DxvkShaderState& stageInfo) const;
DxvkShaderStageState* getShaderStage(
VkShaderStageFlagBits stage);
};

View File

@ -3,6 +3,7 @@
#include "dxvk_buffer.h"
#include "dxvk_compute.h"
#include "dxvk_framebuffer.h"
#include "dxvk_graphics.h"
#include "dxvk_image.h"
#include "dxvk_limits.h"
#include "dxvk_shader.h"
@ -16,87 +17,64 @@ namespace dxvk {
* graphics pipeline has changed and/or needs to
* be updated.
*/
enum class DxvkGraphicsPipelineBit : uint64_t {
RenderPassBound = 0, ///< If set, a render pass instance is currently active
PipelineDirty = 1, ///< If set, the shader pipeline binding is out of date
PipelineStateDirty = 2, ///< If set, another pipeline variant needs to be bound
DirtyResources = 3, ///< If set, the descriptor set must be updated
DirtyVertexBuffers = 4, ///< If set, the vertex buffer bindings need to be updated
DirtyIndexBuffer = 5, ///< If set, the index buffer binding needs to be updated
enum class DxvkContextFlag : uint64_t {
GpRenderPassBound, ///< Render pass is currently bound
GpDirtyPipeline, ///< Graphics pipeline binding are out of date
GpDirtyPipelineState, ///< Graphics pipeline state (blending etc.) is dirty
GpDirtyResources, ///< Graphics pipeline resource bindings are out of date
GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date
GpDirtyIndexBuffers, ///< Index buffer binding are out of date
CpDirtyPipeline, ///< Compute pipeline binding are out of date
CpDirtyResources, ///< Compute pipeline resource bindings are out of date
};
using DxvkGraphicsPipelineFlags = Flags<DxvkGraphicsPipelineBit>;
/**
* \brief Compute pipeline state flags
*
* Stores information on whether the compute shader
* or any of its resource bindings have been updated.
*/
enum class DxvkComputePipelineBit : uint64_t {
PipelineDirty = 0, ///< If set, the shader pipeline binding is out of date
DirtyResources = 1, ///< If set, the descriptor set must be updated
};
using DxvkComputePipelineFlags = Flags<DxvkComputePipelineBit>;
using DxvkContextFlags = Flags<DxvkContextFlag>;
/**
* \brief Shader state
*
* Stores the active shader and resources for a single
* shader stage. This includes sampled textures, uniform
* buffers, storage buffers and storage images.
* Stores the active shader and resources
* for a single shader stage. All stages
* support the same types of resources.
*/
struct DxvkShaderState {
Rc<DxvkShader> shader;
std::array<DxvkBufferBinding, MaxNumStorageBuffers> boundStorageBuffers;
std::array<DxvkBufferBinding, MaxNumUniformBuffers> boundUniformBuffers;
struct DxvkShaderStageState {
Rc<DxvkShader> shader;
};
/**
* \brief Graphics pipeline state
* \brief Output merger state
*
* Stores everything related to graphics
* operations, including bound resources.
* Stores the active framebuffer and the current
* blend state, as well as the depth stencil state.
*/
struct DxvkGraphicsPipelineState {
DxvkShaderState vs;
DxvkShaderState tcs;
DxvkShaderState tes;
DxvkShaderState gs;
DxvkShaderState fs;
Rc<DxvkFramebuffer> fb;
DxvkGraphicsPipelineFlags flags;
struct DxvkOutputMergerState {
Rc<DxvkFramebuffer> framebuffer;
};
/**
* \brief Compute pipeline state
* \brief Pipeline state
*
* Stores the active compute pipeline and
* resources bound to the compute shader.
*/
struct DxvkComputePipelineState {
DxvkShaderState cs;
Rc<DxvkComputePipeline> pipeline;
DxvkComputePipelineFlags flags;
};
/**
* \brief DXVK context state
*
* Stores all graphics pipeline state known
* to DXVK. As in Vulkan, graphics and compute
* pipeline states are strictly separated.
* Stores all bound shaders, resources,
* and constant pipeline state objects.
*/
struct DxvkContextState {
DxvkGraphicsPipelineState g;
DxvkComputePipelineState c;
DxvkShaderStageState vs;
DxvkShaderStageState tcs;
DxvkShaderStageState tes;
DxvkShaderStageState gs;
DxvkShaderStageState fs;
DxvkShaderStageState cs;
DxvkOutputMergerState om;
Rc<DxvkGraphicsPipeline> activeGraphicsPipeline;
Rc<DxvkComputePipeline> activeComputePipeline;
DxvkContextFlags flags;
};
}

View File

@ -8,7 +8,7 @@ namespace dxvk {
bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const {
// TODO implement
return this->renderPass == other.renderPass;
}

View File

@ -9,6 +9,11 @@
namespace dxvk {
/**
* \brief Graphics pipeline state info
*
*
*/
struct DxvkGraphicsPipelineStateInfo {
VkRenderPass renderPass;
@ -18,6 +23,7 @@ namespace dxvk {
bool operator != (const DxvkGraphicsPipelineStateInfo& other) const;
};
/**
* \brief Graphics pipeline
*

View File

@ -28,38 +28,6 @@ public:
})),
m_dxvkContext (m_dxvkDevice->createContext()),
m_dxvkCommandList (m_dxvkDevice->createCommandList()) {
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = sizeof(m_testData);
bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_HOST_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
bufferInfo.access = VK_ACCESS_HOST_WRITE_BIT
| VK_ACCESS_HOST_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT;
m_testBuffer = m_dxvkDevice->createBuffer(bufferInfo,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
for (size_t i = 0; i < 64; i++)
m_testData[i] = static_cast<int>(i);
std::memcpy(m_testBuffer->mapPtr(),
m_testData, sizeof(m_testData));
DxvkResourceSlot computeBufferSlot;
computeBufferSlot.mode.set(
DxvkResourceModeBit::Read,
DxvkResourceModeBit::Write);
computeBufferSlot.type = DxvkResourceType::StorageBuffer;
computeBufferSlot.slot = 0;
SpirvCodeBuffer code(std::ifstream("comp.spv", std::ios::binary));
code.store(std::ofstream("comp.2.spv", std::ios::binary));
m_compShader = new DxvkShader(
VK_SHADER_STAGE_COMPUTE_BIT, std::move(code),
1, &computeBufferSlot);
}
~TriangleApp() {
@ -92,22 +60,12 @@ public:
m_dxvkContext->clearRenderTarget(
clearAttachment,
clearArea);
m_dxvkContext->bindShader(
VK_SHADER_STAGE_COMPUTE_BIT,
m_compShader);
m_dxvkContext->bindStorageBuffer(
VK_SHADER_STAGE_COMPUTE_BIT, 0,
m_testBuffer, 0, sizeof(m_testData));
m_dxvkContext->dispatch(1, 1, 1);
m_dxvkContext->endRecording();
auto fence = m_dxvkDevice->submitCommandList(
m_dxvkCommandList, sync1, sync2);
m_dxvkSwapchain->present(sync2);
m_dxvkDevice->waitForIdle();
std::memcpy(m_testData, m_testBuffer->mapPtr(), sizeof(m_testData));
std::cout << m_testData[0] << std::endl;
}
private:
@ -120,13 +78,6 @@ private:
Rc<DxvkContext> m_dxvkContext;
Rc<DxvkCommandList> m_dxvkCommandList;
Rc<DxvkBuffer> m_testBuffer;
Rc<DxvkShader> m_compShader;
Rc<DxvkShader> m_vertShader;
Rc<DxvkShader> m_fragShader;
int m_testData[64];
};
LRESULT CALLBACK WindowProc(HWND hWnd,