[dxvk] Implement clearBufferView and clearImageView

This commit is contained in:
Philip Rebohle 2018-04-11 23:13:34 +02:00
parent cce578d67a
commit 9d84e1bfaa
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 247 additions and 6 deletions

View File

@ -301,6 +301,19 @@ namespace dxvk {
return m_physView->handle();
}
/**
* \brief Element cound
*
* Number of typed elements contained
* in the buffer view. Depends on the
* buffer view format.
* \returns Element count
*/
VkDeviceSize elementCount() const {
auto format = imageFormatInfo(m_info.format);
return m_info.rangeLength / format->elementSize;
}
/**
* \brief Buffer view properties
* \returns Buffer view properties

View File

@ -182,6 +182,15 @@ namespace dxvk {
}
void updateDescriptorSets(
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites) {
m_vkd->vkUpdateDescriptorSets(m_vkd->device(),
descriptorWriteCount, pDescriptorWrites,
0, nullptr);
}
void updateDescriptorSetWithTemplate(
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplateKHR descriptorTemplate,

View File

@ -242,7 +242,66 @@ namespace dxvk {
VkDeviceSize offset,
VkDeviceSize length,
VkClearColorValue value) {
this->renderPassEnd();
this->unbindComputePipeline();
// Query pipeline objects to use for this clear operation
DxvkMetaClearPipeline pipeInfo = m_metaClear->getClearBufferPipeline(
imageFormatInfo(bufferView->info().format)->flags);
// Create a descriptor set pointing to the view
VkBufferView viewObject = bufferView->handle();
VkDescriptorSet descriptorSet =
m_cmd->allocateDescriptorSet(pipeInfo.dsetLayout);
VkWriteDescriptorSet descriptorWrite;
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.pNext = nullptr;
descriptorWrite.dstSet = descriptorSet;
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorCount = 1;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
descriptorWrite.pImageInfo = nullptr;
descriptorWrite.pBufferInfo = nullptr;
descriptorWrite.pTexelBufferView = &viewObject;
m_cmd->updateDescriptorSets(1, &descriptorWrite);
// Prepare shader arguments
DxvkMetaClearArgs pushArgs;
pushArgs.clearValue = value;
pushArgs.offset = VkOffset3D { int32_t(offset), 0, 0 };
pushArgs.extent = VkExtent3D { uint32_t(length), 1, 1 };
VkExtent3D workgroups = util::computeBlockCount(
pushArgs.extent, pipeInfo.workgroupSize);
m_cmd->cmdBindPipeline(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeline);
m_cmd->cmdBindDescriptorSet(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeLayout, descriptorSet);
m_cmd->cmdPushConstants(
pipeInfo.pipeLayout,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pushArgs), &pushArgs);
m_cmd->cmdDispatch(
workgroups.width,
workgroups.height,
workgroups.depth);
m_barriers.accessBuffer(
bufferView->physicalSlice(),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
bufferView->bufferInfo().stages,
bufferView->bufferInfo().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(bufferView->viewResource());
m_cmd->trackResource(bufferView->bufferResource());
}
@ -367,11 +426,81 @@ namespace dxvk {
void DxvkContext::clearImageView(
const Rc<DxvkBufferView>& bufferView,
const Rc<DxvkImageView>& imageView,
VkOffset3D offset,
VkExtent3D extent,
VkClearColorValue value) {
this->renderPassEnd();
this->unbindComputePipeline();
// Query pipeline objects to use for this clear operation
DxvkMetaClearPipeline pipeInfo = m_metaClear->getClearImagePipeline(
imageView->type(), imageFormatInfo(imageView->info().format)->flags);
// Create a descriptor set pointing to the view
VkDescriptorSet descriptorSet =
m_cmd->allocateDescriptorSet(pipeInfo.dsetLayout);
VkDescriptorImageInfo viewInfo;
viewInfo.sampler = VK_NULL_HANDLE;
viewInfo.imageView = imageView->handle();
viewInfo.imageLayout = imageView->imageInfo().layout;
VkWriteDescriptorSet descriptorWrite;
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.pNext = nullptr;
descriptorWrite.dstSet = descriptorSet;
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorCount = 1;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
descriptorWrite.pImageInfo = &viewInfo;
descriptorWrite.pBufferInfo = nullptr;
descriptorWrite.pTexelBufferView = nullptr;
m_cmd->updateDescriptorSets(1, &descriptorWrite);
// Prepare shader arguments
DxvkMetaClearArgs pushArgs;
pushArgs.clearValue = value;
pushArgs.offset = offset;
pushArgs.extent = extent;
VkExtent3D workgroups = util::computeBlockCount(
pushArgs.extent, pipeInfo.workgroupSize);
if (imageView->type() == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
workgroups.height = imageView->subresources().layerCount;
else if (imageView->type() == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
workgroups.depth = imageView->subresources().layerCount;
m_cmd->cmdBindPipeline(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeline);
m_cmd->cmdBindDescriptorSet(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeLayout, descriptorSet);
m_cmd->cmdPushConstants(
pipeInfo.pipeLayout,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pushArgs), &pushArgs);
m_cmd->cmdDispatch(
workgroups.width,
workgroups.height,
workgroups.depth);
m_barriers.accessImage(
imageView->image(),
imageView->subresources(),
imageView->imageInfo().layout,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
imageView->imageInfo().layout,
imageView->imageInfo().stages,
imageView->imageInfo().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(imageView);
m_cmd->trackResource(imageView->image());
}
@ -1402,6 +1531,16 @@ namespace dxvk {
}
void DxvkContext::unbindComputePipeline() {
m_flags.set(
DxvkContextFlag::CpDirtyPipeline,
DxvkContextFlag::CpDirtyPipelineState,
DxvkContextFlag::CpDirtyResources);
m_cpActivePipeline = VK_NULL_HANDLE;
}
void DxvkContext::updateComputePipeline() {
if (m_flags.test(DxvkContextFlag::CpDirtyPipeline)) {
m_flags.clr(DxvkContextFlag::CpDirtyPipeline);

View File

@ -227,13 +227,13 @@ namespace dxvk {
* Can be used to clear sub-regions of storage images
* that are not going to be used as render targets.
* Implicit format conversion will be applied.
* \param [in] bufferView The buffer view
* \param [in] imageView The image view
* \param [in] offset Offset of the rect to clear
* \param [in] extent Extent of the rect to clear
* \param [in] value The clear value
*/
void clearImageView(
const Rc<DxvkBufferView>& bufferView,
const Rc<DxvkImageView>& imageView,
VkOffset3D offset,
VkExtent3D extent,
VkClearColorValue value);
@ -628,6 +628,8 @@ namespace dxvk {
const Rc<DxvkFramebuffer>& framebuffer);
void renderPassUnbindFramebuffer();
void unbindComputePipeline();
void updateComputePipeline();
void updateComputePipelineState();

View File

@ -70,6 +70,47 @@ namespace dxvk {
}
DxvkMetaClearPipeline DxvkMetaClearObjects::getClearBufferPipeline(
DxvkFormatFlags formatFlags) const {
DxvkMetaClearPipeline result;
result.dsetLayout = m_clearBufDsetLayout;
result.pipeLayout = m_clearBufPipeLayout;
result.pipeline = formatFlags.test(DxvkFormatFlag::SampledInteger)
? m_clearPipesU32.clearBuf
: m_clearPipesF32.clearBuf;
result.workgroupSize = VkExtent3D { 128, 1, 1 };
return result;
}
DxvkMetaClearPipeline DxvkMetaClearObjects::getClearImagePipeline(
VkImageViewType viewType,
DxvkFormatFlags formatFlags) const {
const DxvkMetaClearPipelines& pipes
= formatFlags.test(DxvkFormatFlag::SampledInteger)
? m_clearPipesU32 : m_clearPipesF32;
DxvkMetaClearPipeline result;
result.dsetLayout = m_clearImgDsetLayout;
result.pipeLayout = m_clearImgPipeLayout;
auto pipeInfo = [&pipes, viewType] () -> std::pair<VkPipeline, VkExtent3D> {
switch (viewType) {
case VK_IMAGE_VIEW_TYPE_1D: return { pipes.clearImg1D, VkExtent3D { 64, 1, 1 } };
case VK_IMAGE_VIEW_TYPE_2D: return { pipes.clearImg2D, VkExtent3D { 8, 8, 1 } };
case VK_IMAGE_VIEW_TYPE_3D: return { pipes.clearImg3D, VkExtent3D { 4, 4, 4 } };
case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return { pipes.clearImg1DArray, VkExtent3D { 64, 1, 1 } };
case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return { pipes.clearImg2DArray, VkExtent3D { 8, 8, 1 } };
default: return { VkPipeline(VK_NULL_HANDLE), VkExtent3D { 0, 0, 0, } };
}
}();
result.pipeline = pipeInfo.first;
result.workgroupSize = pipeInfo.second;
return result;
}
VkDescriptorSetLayout DxvkMetaClearObjects::createDescriptorSetLayout(
VkDescriptorType descriptorType) {
VkDescriptorSetLayoutBinding bindInfo;

View File

@ -1,8 +1,7 @@
#pragma once
#include "dxvk_barrier.h"
#include "dxvk_cmdlist.h"
#include "dxvk_resource.h"
#include "dxvk_format.h"
#include "dxvk_include.h"
#include "../spirv/spirv_code_buffer.h"
@ -22,6 +21,20 @@ namespace dxvk {
};
/**
* \brief Pipeline-related objects
*
* Use this to bind the pipeline
* and allocate a descriptor set.
*/
struct DxvkMetaClearPipeline {
VkDescriptorSetLayout dsetLayout;
VkPipelineLayout pipeLayout;
VkPipeline pipeline;
VkExtent3D workgroupSize;
};
/**
* \brief Clear shaders and related objects
*
@ -36,6 +49,30 @@ namespace dxvk {
DxvkMetaClearObjects(const Rc<vk::DeviceFn>& vkd);
~DxvkMetaClearObjects();
/**
* \brief Retrieves objects to use for buffers
*
* Returns the pipeline, pipeline layout and descriptor
* set layout which are required to perform a meta clear
* operation on a buffer resource with the given format.
* \param [in] viewType The image virw type
*/
DxvkMetaClearPipeline getClearBufferPipeline(
DxvkFormatFlags formatFlags) const;
/**
* \brief Retrieves objects for a given image view type
*
* Returns the pipeline, pipeline layout and descriptor
* set layout which are required to perform a meta clear
* operation on a resource with the given view type.
* \param [in] viewType The image virw type
* \returns The pipeline-related objects to use
*/
DxvkMetaClearPipeline getClearImagePipeline(
VkImageViewType viewType,
DxvkFormatFlags formatFlags) const;
private:
struct DxvkMetaClearPipelines {