mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-30 22:24:15 +01:00
[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:
parent
4e780f4f60
commit
d1f76b96af
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
149
src/dxvk/dxvk_unbound.cpp
Normal 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
129
src/dxvk/dxvk_unbound.h
Normal 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;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user