mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-07 16:54:14 +01:00
[dxvk] Implement conditional rendering
This commit is contained in:
parent
03f00453ef
commit
acdb989cfa
@ -2032,6 +2032,28 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::setPredicate(
|
||||||
|
const DxvkBufferSlice& predicate,
|
||||||
|
VkConditionalRenderingFlagsEXT flags) {
|
||||||
|
if (!m_state.cond.predicate.matches(predicate)) {
|
||||||
|
m_state.cond.predicate = predicate;
|
||||||
|
|
||||||
|
if (m_predicateWrites.find(predicate.getSliceHandle())
|
||||||
|
!= m_predicateWrites.end()) {
|
||||||
|
spillRenderPass();
|
||||||
|
commitPredicateUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags.set(DxvkContextFlag::GpDirtyPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state.cond.flags != flags) {
|
||||||
|
m_state.cond.flags = flags;
|
||||||
|
m_flags.set(DxvkContextFlag::GpDirtyPredicate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::setBarrierControl(DxvkBarrierControlFlags control) {
|
void DxvkContext::setBarrierControl(DxvkBarrierControlFlags control) {
|
||||||
m_barrierControl = control;
|
m_barrierControl = control;
|
||||||
}
|
}
|
||||||
@ -2055,6 +2077,21 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::writePredicate(
|
||||||
|
const DxvkBufferSlice& predicate,
|
||||||
|
const Rc<DxvkGpuQuery>& query) {
|
||||||
|
DxvkBufferSliceHandle predicateHandle = predicate.getSliceHandle();
|
||||||
|
DxvkGpuQueryHandle queryHandle = query->handle();
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpRenderPassBound))
|
||||||
|
m_predicateWrites.insert({ predicateHandle, queryHandle });
|
||||||
|
else
|
||||||
|
updatePredicate(predicateHandle, queryHandle);
|
||||||
|
|
||||||
|
m_cmd->trackResource(predicate.buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::writeTimestamp(const Rc<DxvkGpuQuery>& query) {
|
void DxvkContext::writeTimestamp(const Rc<DxvkGpuQuery>& query) {
|
||||||
m_queryManager.writeTimestamp(m_cmd, query);
|
m_queryManager.writeTimestamp(m_cmd, query);
|
||||||
}
|
}
|
||||||
@ -2669,6 +2706,30 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::updatePredicate(
|
||||||
|
const DxvkBufferSliceHandle& predicate,
|
||||||
|
const DxvkGpuQueryHandle& query) {
|
||||||
|
m_cmd->cmdCopyQueryPoolResults(
|
||||||
|
query.queryPool, query.queryId, 1,
|
||||||
|
predicate.handle, predicate.offset, sizeof(uint32_t),
|
||||||
|
VK_QUERY_RESULT_WAIT_BIT);
|
||||||
|
|
||||||
|
m_barriers.accessBuffer(predicate,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
|
||||||
|
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::commitPredicateUpdates() {
|
||||||
|
for (const auto& update : m_predicateWrites)
|
||||||
|
updatePredicate(update.first, update.second);
|
||||||
|
|
||||||
|
m_predicateWrites.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::startRenderPass() {
|
void DxvkContext::startRenderPass() {
|
||||||
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
||||||
&& (m_state.om.framebuffer != nullptr)) {
|
&& (m_state.om.framebuffer != nullptr)) {
|
||||||
@ -2710,6 +2771,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
this->renderPassUnbindFramebuffer();
|
this->renderPassUnbindFramebuffer();
|
||||||
this->unbindGraphicsPipeline();
|
this->unbindGraphicsPipeline();
|
||||||
|
this->commitPredicateUpdates();
|
||||||
|
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters);
|
m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters);
|
||||||
}
|
}
|
||||||
@ -2865,6 +2927,33 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::startConditionalRendering() {
|
||||||
|
if (!m_flags.test(DxvkContextFlag::GpCondActive)) {
|
||||||
|
m_flags.set(DxvkContextFlag::GpCondActive);
|
||||||
|
|
||||||
|
auto predicateSlice = m_state.cond.predicate.getSliceHandle();
|
||||||
|
|
||||||
|
VkConditionalRenderingBeginInfoEXT info;
|
||||||
|
info.sType = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT;
|
||||||
|
info.pNext = nullptr;
|
||||||
|
info.buffer = predicateSlice.handle;
|
||||||
|
info.offset = predicateSlice.offset;
|
||||||
|
info.flags = m_state.cond.flags;
|
||||||
|
|
||||||
|
m_cmd->cmdBeginConditionalRendering(&info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::pauseConditionalRendering() {
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpCondActive)) {
|
||||||
|
m_flags.clr(DxvkContextFlag::GpCondActive);
|
||||||
|
|
||||||
|
m_cmd->cmdEndConditionalRendering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::startTransformFeedback() {
|
void DxvkContext::startTransformFeedback() {
|
||||||
if (!m_flags.test(DxvkContextFlag::GpXfbActive)) {
|
if (!m_flags.test(DxvkContextFlag::GpXfbActive)) {
|
||||||
m_flags.set(DxvkContextFlag::GpXfbActive);
|
m_flags.set(DxvkContextFlag::GpXfbActive);
|
||||||
@ -2980,7 +3069,8 @@ namespace dxvk {
|
|||||||
DxvkContextFlag::GpDirtyBlendConstants,
|
DxvkContextFlag::GpDirtyBlendConstants,
|
||||||
DxvkContextFlag::GpDirtyStencilRef,
|
DxvkContextFlag::GpDirtyStencilRef,
|
||||||
DxvkContextFlag::GpDirtyViewport,
|
DxvkContextFlag::GpDirtyViewport,
|
||||||
DxvkContextFlag::GpDirtyDepthBias);
|
DxvkContextFlag::GpDirtyDepthBias,
|
||||||
|
DxvkContextFlag::GpDirtyPredicate);
|
||||||
|
|
||||||
m_gpActivePipeline = VK_NULL_HANDLE;
|
m_gpActivePipeline = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
@ -3442,6 +3532,18 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::updateConditionalRendering() {
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpDirtyPredicate)) {
|
||||||
|
m_flags.clr(DxvkContextFlag::GpDirtyPredicate);
|
||||||
|
|
||||||
|
pauseConditionalRendering();
|
||||||
|
|
||||||
|
if (m_state.cond.predicate.defined())
|
||||||
|
startConditionalRendering();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateDynamicState() {
|
void DxvkContext::updateDynamicState() {
|
||||||
if (m_gpActivePipeline == VK_NULL_HANDLE)
|
if (m_gpActivePipeline == VK_NULL_HANDLE)
|
||||||
return;
|
return;
|
||||||
@ -3549,6 +3651,9 @@ namespace dxvk {
|
|||||||
if (m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback))
|
if (m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback))
|
||||||
this->updateTransformFeedbackState();
|
this->updateTransformFeedbackState();
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpDirtyPredicate))
|
||||||
|
this->updateConditionalRendering();
|
||||||
|
|
||||||
if (m_flags.any(
|
if (m_flags.any(
|
||||||
DxvkContextFlag::GpDirtyDescriptorSet,
|
DxvkContextFlag::GpDirtyDescriptorSet,
|
||||||
DxvkContextFlag::GpDirtyDescriptorOffsets))
|
DxvkContextFlag::GpDirtyDescriptorOffsets))
|
||||||
|
@ -813,6 +813,21 @@ namespace dxvk {
|
|||||||
uint32_t attachment,
|
uint32_t attachment,
|
||||||
const DxvkBlendMode& blendMode);
|
const DxvkBlendMode& blendMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets predicate
|
||||||
|
*
|
||||||
|
* Enables or disables conditional rendering,
|
||||||
|
* depending on whether the given buffer slice
|
||||||
|
* is defined or not. Draw calls and render
|
||||||
|
* target clear commands will get discarded if
|
||||||
|
* the predicate value is either zero or non-zero.
|
||||||
|
* \param [in] predicate The predicate buffer
|
||||||
|
* \param [in] flags Conditional rendering mode
|
||||||
|
*/
|
||||||
|
void setPredicate(
|
||||||
|
const DxvkBufferSlice& predicate,
|
||||||
|
VkConditionalRenderingFlagsEXT flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Sets barrier control flags
|
* \brief Sets barrier control flags
|
||||||
*
|
*
|
||||||
@ -837,6 +852,18 @@ namespace dxvk {
|
|||||||
void signalGpuEvent(
|
void signalGpuEvent(
|
||||||
const Rc<DxvkGpuEvent>& event);
|
const Rc<DxvkGpuEvent>& event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copies query data to predicate buffer
|
||||||
|
*
|
||||||
|
* The given buffer slice can then be passed
|
||||||
|
* to \c setPredicate to enable predication.
|
||||||
|
* \param [in] predicate Predicate buffer
|
||||||
|
* \param [in] query Source query
|
||||||
|
*/
|
||||||
|
void writePredicate(
|
||||||
|
const DxvkBufferSlice& predicate,
|
||||||
|
const Rc<DxvkGpuQuery>& query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Writes to a timestamp query
|
* \brief Writes to a timestamp query
|
||||||
* \param [in] query The timestamp query
|
* \param [in] query The timestamp query
|
||||||
@ -876,6 +903,11 @@ namespace dxvk {
|
|||||||
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
|
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
|
||||||
std::array<uint32_t, MaxNumActiveBindings> m_descOffsets;
|
std::array<uint32_t, MaxNumActiveBindings> m_descOffsets;
|
||||||
|
|
||||||
|
std::unordered_map<
|
||||||
|
DxvkBufferSliceHandle,
|
||||||
|
DxvkGpuQueryHandle,
|
||||||
|
DxvkHash, DxvkEq> m_predicateWrites;
|
||||||
|
|
||||||
void clearImageViewFb(
|
void clearImageViewFb(
|
||||||
const Rc<DxvkImageView>& imageView,
|
const Rc<DxvkImageView>& imageView,
|
||||||
VkOffset3D offset,
|
VkOffset3D offset,
|
||||||
@ -919,6 +951,12 @@ namespace dxvk {
|
|||||||
const VkImageSubresourceLayers& srcSubresources,
|
const VkImageSubresourceLayers& srcSubresources,
|
||||||
VkFormat format);
|
VkFormat format);
|
||||||
|
|
||||||
|
void updatePredicate(
|
||||||
|
const DxvkBufferSliceHandle& predicate,
|
||||||
|
const DxvkGpuQueryHandle& query);
|
||||||
|
|
||||||
|
void commitPredicateUpdates();
|
||||||
|
|
||||||
void startRenderPass();
|
void startRenderPass();
|
||||||
void spillRenderPass();
|
void spillRenderPass();
|
||||||
void clearRenderPass();
|
void clearRenderPass();
|
||||||
@ -935,6 +973,9 @@ namespace dxvk {
|
|||||||
const DxvkRenderTargets& renderTargets,
|
const DxvkRenderTargets& renderTargets,
|
||||||
DxvkRenderPassOps& renderPassOps);
|
DxvkRenderPassOps& renderPassOps);
|
||||||
|
|
||||||
|
void startConditionalRendering();
|
||||||
|
void pauseConditionalRendering();
|
||||||
|
|
||||||
void startTransformFeedback();
|
void startTransformFeedback();
|
||||||
void pauseTransformFeedback();
|
void pauseTransformFeedback();
|
||||||
|
|
||||||
@ -974,6 +1015,8 @@ namespace dxvk {
|
|||||||
void updateTransformFeedbackBuffers();
|
void updateTransformFeedbackBuffers();
|
||||||
void updateTransformFeedbackState();
|
void updateTransformFeedbackState();
|
||||||
|
|
||||||
|
void updateConditionalRendering();
|
||||||
|
|
||||||
void updateDynamicState();
|
void updateDynamicState();
|
||||||
|
|
||||||
bool validateComputeState();
|
bool validateComputeState();
|
||||||
|
@ -22,6 +22,7 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
enum class DxvkContextFlag : uint64_t {
|
enum class DxvkContextFlag : uint64_t {
|
||||||
GpRenderPassBound, ///< Render pass is currently bound
|
GpRenderPassBound, ///< Render pass is currently bound
|
||||||
|
GpCondActive, ///< Conditional rendering is enabled
|
||||||
GpXfbActive, ///< Transform feedback is enabled
|
GpXfbActive, ///< Transform feedback is enabled
|
||||||
GpClearRenderTargets, ///< Render targets need to be cleared
|
GpClearRenderTargets, ///< Render targets need to be cleared
|
||||||
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
|
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
|
||||||
@ -38,6 +39,7 @@ namespace dxvk {
|
|||||||
GpDirtyDepthBias, ///< Depth bias has changed
|
GpDirtyDepthBias, ///< Depth bias has changed
|
||||||
GpDirtyStencilRef, ///< Stencil reference has changed
|
GpDirtyStencilRef, ///< Stencil reference has changed
|
||||||
GpDirtyViewport, ///< Viewport state has changed
|
GpDirtyViewport, ///< Viewport state has changed
|
||||||
|
GpDirtyPredicate, ///< Predicate has changed
|
||||||
GpDynamicBlendConstants, ///< Blend constants are dynamic
|
GpDynamicBlendConstants, ///< Blend constants are dynamic
|
||||||
GpDynamicDepthBias, ///< Depth bias is dynamic
|
GpDynamicDepthBias, ///< Depth bias is dynamic
|
||||||
GpDynamicStencilRef, ///< Stencil reference is dynamic
|
GpDynamicStencilRef, ///< Stencil reference is dynamic
|
||||||
@ -136,6 +138,12 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkCondRenderState {
|
||||||
|
DxvkBufferSlice predicate;
|
||||||
|
VkConditionalRenderingFlagsEXT flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Pipeline state
|
* \brief Pipeline state
|
||||||
*
|
*
|
||||||
@ -149,6 +157,7 @@ namespace dxvk {
|
|||||||
DxvkOutputMergerState om;
|
DxvkOutputMergerState om;
|
||||||
DxvkXfbState xfb;
|
DxvkXfbState xfb;
|
||||||
DxvkDynamicState dyn;
|
DxvkDynamicState dyn;
|
||||||
|
DxvkCondRenderState cond;
|
||||||
|
|
||||||
DxvkGraphicsPipelineState gp;
|
DxvkGraphicsPipelineState gp;
|
||||||
DxvkComputePipelineState cp;
|
DxvkComputePipelineState cp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user