mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxvk] Implement transform feedback
Begins transform feedback when rendering with an xfb-enabled pipeline bound, and ends transform feedback as needed, while writing back the counters supplied by the app. This does not yet support transform feedback queries or the draw command.
This commit is contained in:
parent
a27e440272
commit
93b1b9bc00
@ -273,7 +273,9 @@ namespace dxvk {
|
||||
* \returns The physical buffer slice
|
||||
*/
|
||||
DxvkPhysicalBufferSlice physicalSlice() const {
|
||||
return m_buffer->subSlice(m_offset, m_length);
|
||||
return m_buffer != nullptr
|
||||
? m_buffer->subSlice(m_offset, m_length)
|
||||
: DxvkPhysicalBufferSlice();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -301,7 +303,9 @@ namespace dxvk {
|
||||
* \returns Pointer into mapped buffer memory
|
||||
*/
|
||||
void* mapPtr(VkDeviceSize offset) const {
|
||||
return m_buffer->mapPtr(m_offset + offset);
|
||||
return m_buffer != nullptr
|
||||
? m_buffer->mapPtr(m_offset + offset)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,7 +134,9 @@ namespace dxvk {
|
||||
* \returns Buffer handle
|
||||
*/
|
||||
VkBuffer handle() const {
|
||||
return m_buffer->handle();
|
||||
return m_buffer != nullptr
|
||||
? m_buffer->handle()
|
||||
: VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,6 +36,7 @@ namespace dxvk {
|
||||
// before any draw or dispatch command is recorded.
|
||||
m_flags.clr(
|
||||
DxvkContextFlag::GpRenderPassBound,
|
||||
DxvkContextFlag::GpXfbActive,
|
||||
DxvkContextFlag::GpClearRenderTargets);
|
||||
|
||||
m_flags.set(
|
||||
@ -44,6 +45,7 @@ namespace dxvk {
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||
DxvkContextFlag::GpDirtyXfbBuffers,
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyPipelineState,
|
||||
DxvkContextFlag::CpDirtyResources,
|
||||
@ -222,6 +224,8 @@ namespace dxvk {
|
||||
uint32_t binding,
|
||||
const DxvkBufferSlice& buffer,
|
||||
const DxvkBufferSlice& counter) {
|
||||
this->spillRenderPass();
|
||||
|
||||
m_state.xfb.buffers [binding] = buffer;
|
||||
m_state.xfb.counters[binding] = counter;
|
||||
|
||||
@ -1151,6 +1155,9 @@ namespace dxvk {
|
||||
if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
||||
|
||||
if (usage & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT)
|
||||
m_flags.set(DxvkContextFlag::GpDirtyXfbBuffers);
|
||||
|
||||
if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
|
||||
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
||||
@ -2163,6 +2170,8 @@ namespace dxvk {
|
||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
||||
m_flags.clr(DxvkContextFlag::GpRenderPassBound);
|
||||
|
||||
this->pauseTransformFeedback();
|
||||
|
||||
m_queries.endQueries(m_cmd, VK_QUERY_TYPE_OCCLUSION);
|
||||
m_queries.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS);
|
||||
|
||||
@ -2243,6 +2252,52 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::startTransformFeedback() {
|
||||
if (!m_flags.test(DxvkContextFlag::GpXfbActive)) {
|
||||
m_flags.set(DxvkContextFlag::GpXfbActive);
|
||||
|
||||
VkBuffer ctrBuffers[MaxNumXfbBuffers];
|
||||
VkDeviceSize ctrOffsets[MaxNumXfbBuffers];
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) {
|
||||
auto physSlice = m_state.xfb.counters[i].physicalSlice();
|
||||
|
||||
ctrBuffers[i] = physSlice.handle();
|
||||
ctrOffsets[i] = physSlice.offset();
|
||||
|
||||
if (physSlice.handle() != VK_NULL_HANDLE)
|
||||
m_cmd->trackResource(physSlice.resource());
|
||||
}
|
||||
|
||||
m_cmd->cmdBeginTransformFeedback(
|
||||
0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::pauseTransformFeedback() {
|
||||
if (m_flags.test(DxvkContextFlag::GpXfbActive)) {
|
||||
m_flags.clr(DxvkContextFlag::GpXfbActive);
|
||||
|
||||
VkBuffer ctrBuffers[MaxNumXfbBuffers];
|
||||
VkDeviceSize ctrOffsets[MaxNumXfbBuffers];
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumXfbBuffers; i++) {
|
||||
auto physSlice = m_state.xfb.counters[i].physicalSlice();
|
||||
|
||||
ctrBuffers[i] = physSlice.handle();
|
||||
ctrOffsets[i] = physSlice.offset();
|
||||
|
||||
if (physSlice.handle() != VK_NULL_HANDLE)
|
||||
m_cmd->trackResource(physSlice.resource());
|
||||
}
|
||||
|
||||
m_cmd->cmdEndTransformFeedback(
|
||||
0, MaxNumXfbBuffers, ctrBuffers, ctrOffsets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::unbindComputePipeline() {
|
||||
m_flags.set(
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
@ -2289,7 +2344,8 @@ namespace dxvk {
|
||||
DxvkContextFlag::GpDirtyPipelineState,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||
DxvkContextFlag::GpDirtyXfbBuffers);
|
||||
|
||||
m_gpActivePipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
@ -2315,6 +2371,8 @@ namespace dxvk {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
||||
|
||||
this->pauseTransformFeedback();
|
||||
|
||||
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
|
||||
const uint32_t binding = m_state.gp.state.ilBindings[i].binding;
|
||||
|
||||
@ -2677,6 +2735,50 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateTransformFeedbackBuffers() {
|
||||
VkBuffer xfbBuffers[MaxNumXfbBuffers];
|
||||
VkDeviceSize xfbOffsets[MaxNumXfbBuffers];
|
||||
VkDeviceSize xfbLengths[MaxNumXfbBuffers];
|
||||
|
||||
for (size_t i = 0; i < MaxNumXfbBuffers; i++) {
|
||||
auto physSlice = m_state.xfb.buffers[i].physicalSlice();
|
||||
|
||||
xfbBuffers[i] = physSlice.handle();
|
||||
xfbOffsets[i] = physSlice.offset();
|
||||
xfbLengths[i] = physSlice.length();
|
||||
|
||||
if (physSlice.handle() == VK_NULL_HANDLE)
|
||||
xfbBuffers[i] = m_device->dummyBufferHandle();
|
||||
|
||||
if (physSlice.handle() != VK_NULL_HANDLE)
|
||||
m_cmd->trackResource(physSlice.resource());
|
||||
}
|
||||
|
||||
m_cmd->cmdBindTransformFeedbackBuffers(
|
||||
0, MaxNumXfbBuffers,
|
||||
xfbBuffers, xfbOffsets, xfbLengths);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateTransformFeedbackState() {
|
||||
bool hasTransformFeedback =
|
||||
m_state.gp.pipeline != nullptr
|
||||
&& m_state.gp.pipeline->flags().test(DxvkGraphicsPipelineFlag::HasTransformFeedback);
|
||||
|
||||
if (!hasTransformFeedback)
|
||||
return;
|
||||
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyXfbBuffers)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyXfbBuffers);
|
||||
|
||||
this->pauseTransformFeedback();
|
||||
this->updateTransformFeedbackBuffers();
|
||||
}
|
||||
|
||||
this->startTransformFeedback();
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateDynamicState() {
|
||||
@ -2743,6 +2845,7 @@ namespace dxvk {
|
||||
this->updateVertexBufferBindings();
|
||||
this->updateGraphicsShaderResources();
|
||||
this->updateGraphicsPipelineState();
|
||||
this->updateTransformFeedbackState();
|
||||
this->updateGraphicsShaderDescriptors();
|
||||
this->updateDynamicState();
|
||||
}
|
||||
|
@ -788,6 +788,9 @@ namespace dxvk {
|
||||
const DxvkRenderTargets& renderTargets,
|
||||
DxvkRenderPassOps& renderPassOps);
|
||||
|
||||
void startTransformFeedback();
|
||||
void pauseTransformFeedback();
|
||||
|
||||
void unbindComputePipeline();
|
||||
void updateComputePipeline();
|
||||
void updateComputePipelineState();
|
||||
@ -820,6 +823,9 @@ namespace dxvk {
|
||||
|
||||
void updateIndexBufferBinding();
|
||||
void updateVertexBufferBindings();
|
||||
|
||||
void updateTransformFeedbackBuffers();
|
||||
void updateTransformFeedbackState();
|
||||
|
||||
void updateDynamicState();
|
||||
|
||||
|
@ -135,6 +135,8 @@ namespace dxvk {
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT |
|
||||
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT |
|
||||
VK_ACCESS_SHADER_WRITE_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
@ -144,7 +146,8 @@ namespace dxvk {
|
||||
VK_ACCESS_SHADER_READ_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT |
|
||||
VK_ACCESS_UNIFORM_READ_BIT |
|
||||
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, 0 },
|
||||
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
|
||||
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, 0 },
|
||||
}};
|
||||
|
||||
VkRenderPassCreateInfo info;
|
||||
|
Loading…
x
Reference in New Issue
Block a user