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

[dxvk] Implement conditional rendering

This commit is contained in:
Philip Rebohle 2019-03-24 01:36:46 +01:00
parent 03f00453ef
commit acdb989cfa
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 159 additions and 2 deletions

View File

@ -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) {
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) {
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() {
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
&& (m_state.om.framebuffer != nullptr)) {
@ -2710,6 +2771,7 @@ namespace dxvk {
this->renderPassUnbindFramebuffer();
this->unbindGraphicsPipeline();
this->commitPredicateUpdates();
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() {
if (!m_flags.test(DxvkContextFlag::GpXfbActive)) {
m_flags.set(DxvkContextFlag::GpXfbActive);
@ -2980,7 +3069,8 @@ namespace dxvk {
DxvkContextFlag::GpDirtyBlendConstants,
DxvkContextFlag::GpDirtyStencilRef,
DxvkContextFlag::GpDirtyViewport,
DxvkContextFlag::GpDirtyDepthBias);
DxvkContextFlag::GpDirtyDepthBias,
DxvkContextFlag::GpDirtyPredicate);
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() {
if (m_gpActivePipeline == VK_NULL_HANDLE)
return;
@ -3549,6 +3651,9 @@ namespace dxvk {
if (m_state.gp.flags.test(DxvkGraphicsPipelineFlag::HasTransformFeedback))
this->updateTransformFeedbackState();
if (m_flags.test(DxvkContextFlag::GpDirtyPredicate))
this->updateConditionalRendering();
if (m_flags.any(
DxvkContextFlag::GpDirtyDescriptorSet,
DxvkContextFlag::GpDirtyDescriptorOffsets))

View File

@ -813,6 +813,21 @@ namespace dxvk {
uint32_t attachment,
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
*
@ -837,6 +852,18 @@ namespace dxvk {
void signalGpuEvent(
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
* \param [in] query The timestamp query
@ -876,6 +903,11 @@ namespace dxvk {
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
std::array<uint32_t, MaxNumActiveBindings> m_descOffsets;
std::unordered_map<
DxvkBufferSliceHandle,
DxvkGpuQueryHandle,
DxvkHash, DxvkEq> m_predicateWrites;
void clearImageViewFb(
const Rc<DxvkImageView>& imageView,
VkOffset3D offset,
@ -919,6 +951,12 @@ namespace dxvk {
const VkImageSubresourceLayers& srcSubresources,
VkFormat format);
void updatePredicate(
const DxvkBufferSliceHandle& predicate,
const DxvkGpuQueryHandle& query);
void commitPredicateUpdates();
void startRenderPass();
void spillRenderPass();
void clearRenderPass();
@ -935,6 +973,9 @@ namespace dxvk {
const DxvkRenderTargets& renderTargets,
DxvkRenderPassOps& renderPassOps);
void startConditionalRendering();
void pauseConditionalRendering();
void startTransformFeedback();
void pauseTransformFeedback();
@ -974,6 +1015,8 @@ namespace dxvk {
void updateTransformFeedbackBuffers();
void updateTransformFeedbackState();
void updateConditionalRendering();
void updateDynamicState();
bool validateComputeState();

View File

@ -22,6 +22,7 @@ namespace dxvk {
*/
enum class DxvkContextFlag : uint64_t {
GpRenderPassBound, ///< Render pass is currently bound
GpCondActive, ///< Conditional rendering is enabled
GpXfbActive, ///< Transform feedback is enabled
GpClearRenderTargets, ///< Render targets need to be cleared
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
@ -38,6 +39,7 @@ namespace dxvk {
GpDirtyDepthBias, ///< Depth bias has changed
GpDirtyStencilRef, ///< Stencil reference has changed
GpDirtyViewport, ///< Viewport state has changed
GpDirtyPredicate, ///< Predicate has changed
GpDynamicBlendConstants, ///< Blend constants are dynamic
GpDynamicDepthBias, ///< Depth bias is dynamic
GpDynamicStencilRef, ///< Stencil reference is dynamic
@ -136,6 +138,12 @@ namespace dxvk {
};
struct DxvkCondRenderState {
DxvkBufferSlice predicate;
VkConditionalRenderingFlagsEXT flags;
};
/**
* \brief Pipeline state
*
@ -149,6 +157,7 @@ namespace dxvk {
DxvkOutputMergerState om;
DxvkXfbState xfb;
DxvkDynamicState dyn;
DxvkCondRenderState cond;
DxvkGraphicsPipelineState gp;
DxvkComputePipelineState cp;