mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-15 07:29:17 +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
|
* \returns The physical buffer slice
|
||||||
*/
|
*/
|
||||||
DxvkPhysicalBufferSlice physicalSlice() const {
|
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
|
* \returns Pointer into mapped buffer memory
|
||||||
*/
|
*/
|
||||||
void* mapPtr(VkDeviceSize offset) const {
|
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
|
* \returns Buffer handle
|
||||||
*/
|
*/
|
||||||
VkBuffer handle() const {
|
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.
|
// before any draw or dispatch command is recorded.
|
||||||
m_flags.clr(
|
m_flags.clr(
|
||||||
DxvkContextFlag::GpRenderPassBound,
|
DxvkContextFlag::GpRenderPassBound,
|
||||||
|
DxvkContextFlag::GpXfbActive,
|
||||||
DxvkContextFlag::GpClearRenderTargets);
|
DxvkContextFlag::GpClearRenderTargets);
|
||||||
|
|
||||||
m_flags.set(
|
m_flags.set(
|
||||||
@ -44,6 +45,7 @@ namespace dxvk {
|
|||||||
DxvkContextFlag::GpDirtyResources,
|
DxvkContextFlag::GpDirtyResources,
|
||||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||||
DxvkContextFlag::GpDirtyIndexBuffer,
|
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||||
|
DxvkContextFlag::GpDirtyXfbBuffers,
|
||||||
DxvkContextFlag::CpDirtyPipeline,
|
DxvkContextFlag::CpDirtyPipeline,
|
||||||
DxvkContextFlag::CpDirtyPipelineState,
|
DxvkContextFlag::CpDirtyPipelineState,
|
||||||
DxvkContextFlag::CpDirtyResources,
|
DxvkContextFlag::CpDirtyResources,
|
||||||
@ -222,6 +224,8 @@ namespace dxvk {
|
|||||||
uint32_t binding,
|
uint32_t binding,
|
||||||
const DxvkBufferSlice& buffer,
|
const DxvkBufferSlice& buffer,
|
||||||
const DxvkBufferSlice& counter) {
|
const DxvkBufferSlice& counter) {
|
||||||
|
this->spillRenderPass();
|
||||||
|
|
||||||
m_state.xfb.buffers [binding] = buffer;
|
m_state.xfb.buffers [binding] = buffer;
|
||||||
m_state.xfb.counters[binding] = counter;
|
m_state.xfb.counters[binding] = counter;
|
||||||
|
|
||||||
@ -1151,6 +1155,9 @@ namespace dxvk {
|
|||||||
if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
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
|
if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
|
||||||
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
|
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
|
||||||
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
||||||
@ -2163,6 +2170,8 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
||||||
m_flags.clr(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_OCCLUSION);
|
||||||
m_queries.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS);
|
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() {
|
void DxvkContext::unbindComputePipeline() {
|
||||||
m_flags.set(
|
m_flags.set(
|
||||||
DxvkContextFlag::CpDirtyPipeline,
|
DxvkContextFlag::CpDirtyPipeline,
|
||||||
@ -2289,7 +2344,8 @@ namespace dxvk {
|
|||||||
DxvkContextFlag::GpDirtyPipelineState,
|
DxvkContextFlag::GpDirtyPipelineState,
|
||||||
DxvkContextFlag::GpDirtyResources,
|
DxvkContextFlag::GpDirtyResources,
|
||||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||||
|
DxvkContextFlag::GpDirtyXfbBuffers);
|
||||||
|
|
||||||
m_gpActivePipeline = VK_NULL_HANDLE;
|
m_gpActivePipeline = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
@ -2315,6 +2371,8 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
|
||||||
|
|
||||||
|
this->pauseTransformFeedback();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
|
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
|
||||||
const uint32_t binding = m_state.gp.state.ilBindings[i].binding;
|
const uint32_t binding = m_state.gp.state.ilBindings[i].binding;
|
||||||
|
|
||||||
@ -2679,6 +2737,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() {
|
void DxvkContext::updateDynamicState() {
|
||||||
if (m_gpActivePipeline == VK_NULL_HANDLE)
|
if (m_gpActivePipeline == VK_NULL_HANDLE)
|
||||||
return;
|
return;
|
||||||
@ -2743,6 +2845,7 @@ namespace dxvk {
|
|||||||
this->updateVertexBufferBindings();
|
this->updateVertexBufferBindings();
|
||||||
this->updateGraphicsShaderResources();
|
this->updateGraphicsShaderResources();
|
||||||
this->updateGraphicsPipelineState();
|
this->updateGraphicsPipelineState();
|
||||||
|
this->updateTransformFeedbackState();
|
||||||
this->updateGraphicsShaderDescriptors();
|
this->updateGraphicsShaderDescriptors();
|
||||||
this->updateDynamicState();
|
this->updateDynamicState();
|
||||||
}
|
}
|
||||||
|
@ -788,6 +788,9 @@ namespace dxvk {
|
|||||||
const DxvkRenderTargets& renderTargets,
|
const DxvkRenderTargets& renderTargets,
|
||||||
DxvkRenderPassOps& renderPassOps);
|
DxvkRenderPassOps& renderPassOps);
|
||||||
|
|
||||||
|
void startTransformFeedback();
|
||||||
|
void pauseTransformFeedback();
|
||||||
|
|
||||||
void unbindComputePipeline();
|
void unbindComputePipeline();
|
||||||
void updateComputePipeline();
|
void updateComputePipeline();
|
||||||
void updateComputePipelineState();
|
void updateComputePipelineState();
|
||||||
@ -821,6 +824,9 @@ namespace dxvk {
|
|||||||
void updateIndexBufferBinding();
|
void updateIndexBufferBinding();
|
||||||
void updateVertexBufferBindings();
|
void updateVertexBufferBindings();
|
||||||
|
|
||||||
|
void updateTransformFeedbackBuffers();
|
||||||
|
void updateTransformFeedbackState();
|
||||||
|
|
||||||
void updateDynamicState();
|
void updateDynamicState();
|
||||||
|
|
||||||
bool validateComputeState();
|
bool validateComputeState();
|
||||||
|
@ -135,6 +135,8 @@ namespace dxvk {
|
|||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
VK_ACCESS_DEPTH_STENCIL_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_SHADER_WRITE_BIT,
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||||
@ -144,7 +146,8 @@ namespace dxvk {
|
|||||||
VK_ACCESS_SHADER_READ_BIT |
|
VK_ACCESS_SHADER_READ_BIT |
|
||||||
VK_ACCESS_TRANSFER_READ_BIT |
|
VK_ACCESS_TRANSFER_READ_BIT |
|
||||||
VK_ACCESS_UNIFORM_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;
|
VkRenderPassCreateInfo info;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user