diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index fa2082253..61a62fd4f 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -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 finalize() = 0; - /** - * \brief Creates code generator for a given program type - * - * \param [in] version Program version - * \returns The code generator - */ static Rc create( const DxbcProgramVersion& version); diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 4dfb6c259..278a55eaa 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -21,38 +21,34 @@ namespace dxvk { void DxvkContext::beginRecording( const Rc& 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& 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& 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& 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 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(stage))); } } - - uint32_t DxvkContext::addResourceBindingInfo( - std::vector& 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; - } - } \ No newline at end of file diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index af66e2240..7fc369834 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -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& 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& 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 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& bindings, - const DxvkShaderState& stageInfo) const; + DxvkShaderStageState* getShaderStage( + VkShaderStageFlagBits stage); }; diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index c2b4a5c10..bc3e39f56 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -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; - - - /** - * \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; + using DxvkContextFlags = Flags; /** * \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 shader; - - std::array boundStorageBuffers; - std::array boundUniformBuffers; + struct DxvkShaderStageState { + Rc 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 fb; - DxvkGraphicsPipelineFlags flags; + struct DxvkOutputMergerState { + Rc 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 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 activeGraphicsPipeline; + Rc activeComputePipeline; + + DxvkContextFlags flags; }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 21311899b..9656d322f 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -8,7 +8,7 @@ namespace dxvk { bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const { - // TODO implement + return this->renderPass == other.renderPass; } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index d00249676..49847ea16 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -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 * diff --git a/tests/dxvk/test_dxvk_triangle.cpp b/tests/dxvk/test_dxvk_triangle.cpp index d0d9cca9e..3441784b8 100644 --- a/tests/dxvk/test_dxvk_triangle.cpp +++ b/tests/dxvk/test_dxvk_triangle.cpp @@ -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(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 m_dxvkContext; Rc m_dxvkCommandList; - Rc m_testBuffer; - Rc m_compShader; - Rc m_vertShader; - Rc m_fragShader; - - int m_testData[64]; - }; LRESULT CALLBACK WindowProc(HWND hWnd,