1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 01:24:11 +01:00

[dxvk] Use new mip map generator

This commit is contained in:
Philip Rebohle 2018-05-25 17:45:41 +02:00
parent 19b6a16173
commit 4b37590e14
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 126 additions and 131 deletions

View File

@ -856,9 +856,7 @@ namespace dxvk {
if (view->GetResourceType() != D3D11_RESOURCE_DIMENSION_BUFFER) {
EmitCs([cDstImageView = view->GetImageView()]
(DxvkContext* ctx) {
ctx->generateMipmaps(
cDstImageView->image(),
cDstImageView->subresources());
ctx->generateMipmaps(cDstImageView);
});
} else {
Logger::err("D3D11: GenerateMips called on a buffer");

View File

@ -7,12 +7,14 @@
namespace dxvk {
DxvkContext::DxvkContext(
const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects)
const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects,
const Rc<DxvkMetaMipGenObjects>& metaMipGenObjects)
: m_device (device),
m_pipeMgr (pipelineManager),
m_metaClear (metaClearObjects) { }
m_metaClear (metaClearObjects),
m_metaMipGen(metaMipGenObjects) { }
DxvkContext::~DxvkContext() {
@ -976,123 +978,102 @@ namespace dxvk {
void DxvkContext::generateMipmaps(
const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources) {
if (subresources.levelCount <= 1)
const Rc<DxvkImageView>& imageView) {
if (imageView->info().numLevels <= 1)
return;
this->spillRenderPass();
// The top-most level will only be read. We can
// discard the contents of all the lower levels
// since we're going to override them anyway.
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask,
subresources.baseMipLevel, 1,
subresources.baseArrayLayer,
subresources.layerCount },
image->info().layout,
image->info().stages,
image->info().access,
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
this->unbindGraphicsPipeline();
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask,
subresources.baseMipLevel + 1,
subresources.levelCount - 1,
subresources.baseArrayLayer,
subresources.layerCount },
VK_IMAGE_LAYOUT_UNDEFINED,
image->info().stages,
image->info().access,
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
// Create the a set of framebuffers and image views
const Rc<DxvkMetaMipGenRenderPass> mipGenerator
= new DxvkMetaMipGenRenderPass(m_device->vkd(), imageView);
m_barriers.recordCommands(m_cmd);
// Common descriptor set properties that we use to
// bind the source image view to the fragment shader
VkDescriptorImageInfo descriptorImage;
descriptorImage.sampler = VK_NULL_HANDLE;
descriptorImage.imageView = VK_NULL_HANDLE;
descriptorImage.imageLayout = imageView->imageInfo().layout;
// Generate each individual mip level with a blit
for (uint32_t i = 1; i < subresources.levelCount; i++) {
const uint32_t mip = subresources.baseMipLevel + i;
VkWriteDescriptorSet descriptorWrite;
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.pNext = nullptr;
descriptorWrite.dstSet = VK_NULL_HANDLE;
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorCount = 1;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrite.pImageInfo = &descriptorImage;
descriptorWrite.pBufferInfo = nullptr;
descriptorWrite.pTexelBufferView = nullptr;
// Common render pass info
VkRenderPassBeginInfo passInfo;
passInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
passInfo.pNext = nullptr;
passInfo.renderPass = mipGenerator->renderPass();
passInfo.framebuffer = VK_NULL_HANDLE;
passInfo.renderArea = VkRect2D { };
passInfo.clearValueCount = 0;
passInfo.pClearValues = nullptr;
// Retrieve a compatible pipeline to use for rendering
DxvkMetaMipGenPipeline pipeInfo = m_metaMipGen->getPipeline(
mipGenerator->viewType(), imageView->info().format);
for (uint32_t i = 0; i < mipGenerator->passCount(); i++) {
DxvkMetaMipGenPass pass = mipGenerator->pass(i);
const VkExtent3D srcExtent = image->mipLevelExtent(mip - 1);
const VkExtent3D dstExtent = image->mipLevelExtent(mip);
// Width, height and layer count for the current pass
VkExtent3D passExtent = mipGenerator->passExtent(i);
VkImageBlit region;
region.srcSubresource = VkImageSubresourceLayers {
subresources.aspectMask, mip - 1,
subresources.baseArrayLayer,
subresources.layerCount };
region.srcOffsets[0] = VkOffset3D { 0, 0, 0 };
region.srcOffsets[1].x = srcExtent.width;
region.srcOffsets[1].y = srcExtent.height;
region.srcOffsets[1].z = srcExtent.depth;
// Create descriptor set with the current source view
descriptorImage.imageView = pass.srcView;
descriptorWrite.dstSet = m_cmd->allocateDescriptorSet(pipeInfo.dsetLayout);
m_cmd->updateDescriptorSets(1, &descriptorWrite);
region.dstSubresource = VkImageSubresourceLayers {
subresources.aspectMask, mip,
subresources.baseArrayLayer,
subresources.layerCount };
region.dstOffsets[0] = VkOffset3D { 0, 0, 0 };
region.dstOffsets[1].x = dstExtent.width;
region.dstOffsets[1].y = dstExtent.height;
region.dstOffsets[1].z = dstExtent.depth;
// Set up viewport and scissor rect
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = float(passExtent.width);
viewport.height = float(passExtent.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
m_cmd->cmdBlitImage(
image->handle(), image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
image->handle(), image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
1, &region, VK_FILTER_LINEAR);
VkRect2D scissor;
scissor.offset = { 0, 0 };
scissor.extent = { passExtent.width, passExtent.height };
if (i + 1 < subresources.levelCount) {
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask, mip, 1,
subresources.baseArrayLayer,
subresources.layerCount },
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd);
}
// Set up render pass info
passInfo.framebuffer = pass.framebuffer;
passInfo.renderArea = scissor;
// Set up push constants
DxvkMetaMipGenPushConstants pushConstants;
pushConstants.layerCount = passExtent.depth;
m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE);
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle);
m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeInfo.pipeLayout, descriptorWrite.dstSet);
m_cmd->cmdSetViewport(0, 1, &viewport);
m_cmd->cmdSetScissor (0, 1, &scissor);
m_cmd->cmdPushConstants(
pipeInfo.pipeLayout,
VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(pushConstants),
&pushConstants);
m_cmd->cmdDraw(1, passExtent.depth, 0, 0);
m_cmd->cmdEndRenderPass();
}
// Transform mip levels back into their original layout.
// The last mip level is still in TRANSFER_DST_OPTIMAL.
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask,
subresources.baseMipLevel,
subresources.levelCount - 1,
subresources.baseArrayLayer,
subresources.layerCount },
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT,
image->info().layout,
image->info().stages,
image->info().access);
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask,
subresources.baseMipLevel
+ subresources.levelCount - 1, 1,
subresources.baseArrayLayer,
subresources.layerCount },
image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
image->info().layout,
image->info().stages,
image->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(mipGenerator);
m_cmd->trackResource(imageView);
}
@ -1680,6 +1661,18 @@ namespace dxvk {
}
void DxvkContext::unbindGraphicsPipeline() {
m_flags.set(
DxvkContextFlag::GpDirtyPipeline,
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyResources,
DxvkContextFlag::GpDirtyVertexBuffers,
DxvkContextFlag::GpDirtyIndexBuffer);
m_gpActivePipeline = VK_NULL_HANDLE;
}
void DxvkContext::updateGraphicsPipeline() {
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);

View File

@ -7,6 +7,7 @@
#include "dxvk_data.h"
#include "dxvk_event.h"
#include "dxvk_meta_clear.h"
#include "dxvk_meta_mipgen.h"
#include "dxvk_meta_resolve.h"
#include "dxvk_pipecache.h"
#include "dxvk_pipemanager.h"
@ -28,9 +29,10 @@ namespace dxvk {
public:
DxvkContext(
const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects);
const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects,
const Rc<DxvkMetaMipGenObjects>& metaMipGenObjects);
~DxvkContext();
/**
@ -403,12 +405,10 @@ namespace dxvk {
*
* Uses blitting to generate lower mip levels from
* the top-most mip level passed to this method.
* \param [in] image The image to generate mips for
* \param [in] subresource The subresource range
* \param [in] imageView The image to generate mips for
*/
void generateMipmaps(
const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources);
const Rc<DxvkImageView>& imageView);
/**
* \brief Initializes or invalidates an image
@ -621,6 +621,7 @@ namespace dxvk {
const Rc<DxvkDevice> m_device;
const Rc<DxvkPipelineManager> m_pipeMgr;
const Rc<DxvkMetaClearObjects> m_metaClear;
const Rc<DxvkMetaMipGenObjects> m_metaMipGen;
Rc<DxvkCommandList> m_cmd;
DxvkContextFlags m_flags;
@ -654,10 +655,10 @@ namespace dxvk {
DxvkRenderPassOps& renderPassOps);
void unbindComputePipeline();
void updateComputePipeline();
void updateComputePipelineState();
void unbindGraphicsPipeline();
void updateGraphicsPipeline();
void updateGraphicsPipelineState();

View File

@ -8,17 +8,18 @@ namespace dxvk {
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkDeviceExtensions>& extensions,
const VkPhysicalDeviceFeatures& features)
: m_adapter (adapter),
m_vkd (vkd),
m_extensions (extensions),
m_features (features),
m_properties (adapter->deviceProperties()),
m_memory (new DxvkMemoryAllocator (adapter, vkd)),
m_renderPassPool (new DxvkRenderPassPool (vkd)),
m_pipelineManager (new DxvkPipelineManager (this)),
m_metaClearObjects(new DxvkMetaClearObjects (vkd)),
m_unboundResources(this),
m_submissionQueue (this) {
: m_adapter (adapter),
m_vkd (vkd),
m_extensions (extensions),
m_features (features),
m_properties (adapter->deviceProperties()),
m_memory (new DxvkMemoryAllocator (adapter, vkd)),
m_renderPassPool (new DxvkRenderPassPool (vkd)),
m_pipelineManager (new DxvkPipelineManager (this)),
m_metaClearObjects (new DxvkMetaClearObjects (vkd)),
m_metaMipGenObjects (new DxvkMetaMipGenObjects(vkd)),
m_unboundResources (this),
m_submissionQueue (this) {
m_graphicsQueue.queueFamily = m_adapter->graphicsQueueFamily();
m_presentQueue.queueFamily = m_adapter->presentQueueFamily();
@ -106,7 +107,8 @@ namespace dxvk {
Rc<DxvkContext> DxvkDevice::createContext() {
return new DxvkContext(this,
m_pipelineManager,
m_metaClearObjects);
m_metaClearObjects,
m_metaMipGenObjects);
}

View File

@ -356,6 +356,7 @@ namespace dxvk {
Rc<DxvkRenderPassPool> m_renderPassPool;
Rc<DxvkPipelineManager> m_pipelineManager;
Rc<DxvkMetaClearObjects> m_metaClearObjects;
Rc<DxvkMetaMipGenObjects> m_metaMipGenObjects;
DxvkUnboundResources m_unboundResources;