[dxvk] Added dummy resources for descriptors

This should finally shut up validation layers and also allows
the branches in texture sample operations to be removed.
This commit is contained in:
Philip Rebohle 2018-01-27 19:25:41 +01:00
parent 4e780f4f60
commit d1f76b96af
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 334 additions and 17 deletions

View File

@ -1288,6 +1288,7 @@ namespace dxvk {
m_cmd->trackResource(res.sampler);
} else {
updatePipelineState |= bs.setUnbound(i);
m_descriptors[i].image = m_device->dummySamplerDescriptor();
} break;
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
@ -1303,6 +1304,7 @@ namespace dxvk {
m_cmd->trackResource(res.imageView->image());
} else {
updatePipelineState |= bs.setUnbound(i);
m_descriptors[i].image = m_device->dummyImageViewDescriptor(binding.view);
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
@ -1316,6 +1318,7 @@ namespace dxvk {
m_cmd->trackResource(res.bufferView->resource());
} else {
updatePipelineState |= bs.setUnbound(i);
m_descriptors[i].texelBuffer = m_device->dummyBufferViewDescriptor();
} break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
@ -1331,6 +1334,7 @@ namespace dxvk {
m_cmd->trackResource(physicalSlice.resource());
} else {
updatePipelineState |= bs.setUnbound(i);
m_descriptors[i].buffer = m_device->dummyBufferDescriptor();
} break;
default:
@ -1355,26 +1359,23 @@ namespace dxvk {
const VkDescriptorSet dset =
m_cmd->allocateDescriptorSet(
layout->descriptorSetLayout());
size_t writeId = 0;
for (uint32_t i = 0; i < layout->bindingCount(); i++) {
if (bindingState.isBound(i)) {
writes[writeId].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[writeId].pNext = nullptr;
writes[writeId].dstSet = dset;
writes[writeId].dstBinding = i;
writes[writeId].dstArrayElement = 0;
writes[writeId].descriptorCount = 1;
writes[writeId].descriptorType = layout->binding(i).type;
writes[writeId].pImageInfo = &m_descriptors[i].image;
writes[writeId].pBufferInfo = &m_descriptors[i].buffer;
writes[writeId].pTexelBufferView = &m_descriptors[i].texelBuffer;
writeId++;
}
const uint32_t bindingCount = layout->bindingCount();
for (uint32_t i = 0; i < bindingCount; i++) {
writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[i].pNext = nullptr;
writes[i].dstSet = dset;
writes[i].dstBinding = i;
writes[i].dstArrayElement = 0;
writes[i].descriptorCount = 1;
writes[i].descriptorType = layout->binding(i).type;
writes[i].pImageInfo = &m_descriptors[i].image;
writes[i].pBufferInfo = &m_descriptors[i].buffer;
writes[i].pTexelBufferView = &m_descriptors[i].texelBuffer;
}
m_cmd->updateDescriptorSet(writeId, writes.data());
m_cmd->updateDescriptorSet(bindingCount, writes.data());
m_cmd->cmdBindDescriptorSet(bindPoint,
layout->pipelineLayout(), dset);
}

View File

@ -16,6 +16,7 @@ namespace dxvk {
m_renderPassPool (new DxvkRenderPassPool (vkd)),
m_pipelineCache (new DxvkPipelineCache (vkd)),
m_pipelineManager (new DxvkPipelineManager(this)),
m_unboundResources(this),
m_submissionQueue (this) {
m_options.adjustAppOptions(env::getExeName());
m_options.adjustDeviceOptions(m_adapter);

View File

@ -20,6 +20,7 @@
#include "dxvk_stats.h"
#include "dxvk_swapchain.h"
#include "dxvk_sync.h"
#include "dxvk_unbound.h"
namespace dxvk {
@ -276,6 +277,40 @@ namespace dxvk {
const Rc<DxvkSurface>& surface,
const DxvkSwapchainProperties& properties);
/**
* \brief Dummy buffer descriptor
* \returns Descriptor that points to a dummy buffer
*/
VkDescriptorBufferInfo dummyBufferDescriptor() const {
return m_unboundResources.bufferDescriptor();
}
/**
* \brief Dummy buffer view descriptor
* \returns Dummy buffer view handle
*/
VkBufferView dummyBufferViewDescriptor() const {
return m_unboundResources.bufferViewDescriptor();
}
/**
* \brief Dummy sampler descriptor
* \returns Descriptor that points to a dummy sampler
*/
VkDescriptorImageInfo dummySamplerDescriptor() const {
return m_unboundResources.samplerDescriptor();
}
/**
* \brief Dummy image view descriptor
*
* \param [in] type Required view type
* \returns Descriptor that points to a dummy image
*/
VkDescriptorImageInfo dummyImageViewDescriptor(VkImageViewType type) const {
return m_unboundResources.imageViewDescriptor(type);
}
/**
* \brief Presents a swap chain image
*
@ -331,6 +366,7 @@ namespace dxvk {
Rc<DxvkPipelineCache> m_pipelineCache;
Rc<DxvkPipelineManager> m_pipelineManager;
DxvkUnboundResources m_unboundResources;
DxvkOptions m_options;
std::mutex m_submissionLock;

149
src/dxvk/dxvk_unbound.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "dxvk_device.h"
namespace dxvk {
DxvkUnboundResources::DxvkUnboundResources(DxvkDevice* dev)
: m_buffer (createBuffer(dev)),
m_bufferView (createBufferView(dev, m_buffer)),
m_image1D (createImage(dev, VK_IMAGE_TYPE_1D, 1)),
m_image2D (createImage(dev, VK_IMAGE_TYPE_2D, 6)),
m_image3D (createImage(dev, VK_IMAGE_TYPE_3D, 1)),
m_view1D (createImageView(dev, m_image1D, VK_IMAGE_VIEW_TYPE_1D, 1)),
m_view1DArr (createImageView(dev, m_image1D, VK_IMAGE_VIEW_TYPE_1D_ARRAY, 1)),
m_view2D (createImageView(dev, m_image2D, VK_IMAGE_VIEW_TYPE_2D, 1)),
m_view2DArr (createImageView(dev, m_image2D, VK_IMAGE_VIEW_TYPE_2D_ARRAY, 1)),
m_viewCube (createImageView(dev, m_image2D, VK_IMAGE_VIEW_TYPE_CUBE, 6)),
m_viewCubeArr (createImageView(dev, m_image2D, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, 6)),
m_view3D (createImageView(dev, m_image3D, VK_IMAGE_VIEW_TYPE_3D, 1)) {
}
DxvkUnboundResources::~DxvkUnboundResources() {
}
Rc<DxvkSampler> DxvkUnboundResources::createSampler(DxvkDevice* dev) {
DxvkSamplerCreateInfo info;
info.minFilter = VK_FILTER_LINEAR;
info.magFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.mipmapLodBias = 0.0f;
info.mipmapLodMin = -256.0f;
info.mipmapLodMax = 256.0f;
info.useAnisotropy = VK_FALSE;
info.maxAnisotropy = 1.0f;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
info.compareToDepth = VK_FALSE;
info.compareOp = VK_COMPARE_OP_NEVER;
info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
info.usePixelCoord = VK_FALSE;
return dev->createSampler(info);
}
Rc<DxvkBuffer> DxvkUnboundResources::createBuffer(DxvkDevice* dev) {
DxvkBufferCreateInfo info;
info.size = 4;
info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
| VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
info.access = VK_ACCESS_UNIFORM_READ_BIT
| VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT;
return dev->createBuffer(info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
Rc<DxvkBufferView> DxvkUnboundResources::createBufferView(
DxvkDevice* dev,
const Rc<DxvkBuffer>& buffer) {
DxvkBufferViewCreateInfo info;
info.format = VK_FORMAT_R32_UINT;
info.rangeOffset = 0;
info.rangeLength = buffer->info().size;
return dev->createBufferView(buffer, info);
}
Rc<DxvkImage> DxvkUnboundResources::createImage(
DxvkDevice* dev,
VkImageType type,
uint32_t layers) {
DxvkImageCreateInfo info;
info.type = type;
info.format = VK_FORMAT_R32_UINT;
info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
info.sampleCount = VK_SAMPLE_COUNT_1_BIT;
info.extent = { 1, 1, 1 };
info.numLayers = layers;
info.mipLevels = 1;
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT
| VK_IMAGE_USAGE_STORAGE_BIT;
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
| VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
info.access = VK_ACCESS_SHADER_READ_BIT;
info.layout = VK_IMAGE_LAYOUT_GENERAL;
info.tiling = VK_IMAGE_TILING_OPTIMAL;
if (type == VK_IMAGE_TYPE_2D)
info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
return dev->createImage(info,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
Rc<DxvkImageView> DxvkUnboundResources::createImageView(
DxvkDevice* dev,
const Rc<DxvkImage>& image,
VkImageViewType type,
uint32_t layers) {
DxvkImageViewCreateInfo info;
info.type = type;
info.format = image->info().format;
info.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
info.minLevel = 0;
info.numLevels = 1;
info.minLayer = 0;
info.numLayers = layers;
info.swizzle = VkComponentMapping {
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO,
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO };
return dev->createImageView(image, info);
}
const DxvkImageView* DxvkUnboundResources::getImageView(VkImageViewType type) const {
switch (type) {
case VK_IMAGE_VIEW_TYPE_1D: return m_view1D.ptr();
case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return m_view1DArr.ptr();
case VK_IMAGE_VIEW_TYPE_2D: return m_view2D.ptr();
case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return m_view2DArr.ptr();
case VK_IMAGE_VIEW_TYPE_CUBE: return m_viewCube.ptr();
case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return m_viewCubeArr.ptr();
case VK_IMAGE_VIEW_TYPE_3D: return m_view3D.ptr();
default: return nullptr;
}
}
}

129
src/dxvk/dxvk_unbound.h Normal file
View File

@ -0,0 +1,129 @@
#pragma once
#include "dxvk_buffer.h"
#include "dxvk_image.h"
#include "dxvk_sampler.h"
namespace dxvk {
/**
* \brief Unbound resources
*
* Creates dummy resources that will be used
* for descriptor sets when the client API did
* not bind a compatible resource to a slot.
*/
class DxvkUnboundResources {
public:
DxvkUnboundResources(DxvkDevice* dev);
~DxvkUnboundResources();
/**
* \brief Dummy buffer descriptor
*
* Points to a tiny buffer with undefined
* values. Do not access this buffer.
* \returns Dummy buffer descriptor
*/
VkDescriptorBufferInfo bufferDescriptor() const {
auto slice = m_buffer->slice();
VkDescriptorBufferInfo result;
result.buffer = slice.handle();
result.offset = slice.offset();
result.range = slice.length();
return result;
}
/**
* \brief Dummy buffer view
*
* Returns an \c R32_UINT view into the
* dummy buffer, which will contain one
* element with undefined value.
* \returns Dummy buffer view
*/
VkBufferView bufferViewDescriptor() const {
return m_bufferView->handle();
}
/**
* \brief Dummy sampler descriptor
*
* Points to a sampler which was created with
* reasonable default values. Client APIs may
* still require different behaviour.
* \returns Dummy sampler descriptor
*/
VkDescriptorImageInfo samplerDescriptor() const {
VkDescriptorImageInfo result;
result.sampler = m_sampler->handle();
result.imageView = VK_NULL_HANDLE;
result.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
return result;
}
/**
* \brief Dummy image view descriptor
*
* Points to an image view which, instead of
* reading image data, will return zeroes for
* all components unconditionally.
* \returns Dummy image view descriptor
*/
VkDescriptorImageInfo imageViewDescriptor(VkImageViewType type) const {
auto view = getImageView(type);
VkDescriptorImageInfo result;
result.sampler = VK_NULL_HANDLE;
result.imageView = view->handle();
result.imageLayout = view->imageInfo().layout;
return result;
}
private:
Rc<DxvkSampler> m_sampler;
Rc<DxvkBuffer> m_buffer;
Rc<DxvkBufferView> m_bufferView;
Rc<DxvkImage> m_image1D;
Rc<DxvkImage> m_image2D;
Rc<DxvkImage> m_image3D;
Rc<DxvkImageView> m_view1D;
Rc<DxvkImageView> m_view1DArr;
Rc<DxvkImageView> m_view2D;
Rc<DxvkImageView> m_view2DArr;
Rc<DxvkImageView> m_viewCube;
Rc<DxvkImageView> m_viewCubeArr;
Rc<DxvkImageView> m_view3D;
Rc<DxvkSampler> createSampler(DxvkDevice* dev);
Rc<DxvkBuffer> createBuffer(DxvkDevice* dev);
Rc<DxvkBufferView> createBufferView(
DxvkDevice* dev,
const Rc<DxvkBuffer>& buffer);
Rc<DxvkImage> createImage(
DxvkDevice* dev,
VkImageType type,
uint32_t layers);
Rc<DxvkImageView> createImageView(
DxvkDevice* dev,
const Rc<DxvkImage>& image,
VkImageViewType type,
uint32_t layers);
const DxvkImageView* getImageView(
VkImageViewType type) const;
};
}

View File

@ -38,6 +38,7 @@ dxvk_src = files([
'dxvk_surface.cpp',
'dxvk_swapchain.cpp',
'dxvk_sync.cpp',
'dxvk_unbound.cpp',
'dxvk_util.cpp',
'hud/dxvk_hud.cpp',