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

[d3d11] Implemented mipmap generation

This commit is contained in:
Philip Rebohle 2018-01-20 09:46:54 +01:00
parent a644eebfd7
commit f88adc4e82
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 156 additions and 1 deletions

View File

@ -651,7 +651,16 @@ namespace dxvk {
void STDMETHODCALLTYPE D3D11DeviceContext::GenerateMips(ID3D11ShaderResourceView* pShaderResourceView) {
Logger::err("D3D11DeviceContext::GenerateMips: Not implemented");
auto view = static_cast<D3D11ShaderResourceView*>(pShaderResourceView);
if (view->GetResourceType() != D3D11_RESOURCE_DIMENSION_BUFFER) {
m_context->generateMipmaps(
view->GetImageView()->image(),
view->GetImageView()->subresources());
} else {
Logger::err("D3D11DeviceContext: GenerateMips called on a buffer");
}
}

View File

@ -141,6 +141,21 @@ namespace dxvk {
}
void cmdBlitImage(
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter) {
m_vkd->vkCmdBlitImage(m_buffer,
srcImage, srcImageLayout,
dstImage, dstImageLayout,
regionCount, pRegions, filter);
}
void cmdClearAttachments(
uint32_t attachmentCount,
const VkClearAttachment* pAttachments,

View File

@ -610,6 +610,125 @@ namespace dxvk {
}
void DxvkContext::generateMipmaps(
const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources) {
if (subresources.levelCount <= 1)
return;
// 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,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
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,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.recordCommands(m_cmd);
// Generate each individual mip level with a blit
for (uint32_t i = 1; i < subresources.levelCount; i++) {
const uint32_t mip = subresources.baseMipLevel + i;
const VkExtent3D srcExtent = image->mipLevelExtent(mip - 1);
const VkExtent3D dstExtent = image->mipLevelExtent(mip);
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;
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;
m_cmd->cmdBlitImage(
image->handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image->handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &region, VK_FILTER_LINEAR);
if (i + 1 < subresources.levelCount) {
m_barriers.accessImage(image,
VkImageSubresourceRange {
subresources.aspectMask, mip, 1,
subresources.baseArrayLayer,
subresources.layerCount },
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd);
}
}
// 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 },
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 },
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);
}
void DxvkContext::invalidateBuffer(const Rc<DxvkBuffer>& buffer) {
// Allocate new backing resource
buffer->rename(buffer->allocPhysicalSlice());

View File

@ -325,6 +325,18 @@ namespace dxvk {
uint32_t count,
uint32_t stride);
/**
* \brief Generates mip maps
*
* 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
*/
void generateMipmaps(
const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources);
/**
* \brief Initializes or invalidates an image
*