mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-18 22:54:15 +01:00
[dxvk] Implement clearBufferView and clearImageView
This commit is contained in:
parent
cce578d67a
commit
9d84e1bfaa
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user