[dxvk] Initialize dummy resources to zero

Read access to unbound images and buffers usually yields
a result vector that contains zeroes in all components.
This commit is contained in:
Philip Rebohle 2018-02-01 14:26:38 +01:00
parent d4a0581f8f
commit c66492a90f
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 174 additions and 46 deletions

View File

@ -196,7 +196,12 @@ namespace dxvk {
if (m_vki->vkCreateDevice(m_handle, &info, nullptr, &device) != VK_SUCCESS)
throw DxvkError("DxvkAdapter: Failed to create device");
return new DxvkDevice(this, new vk::DeviceFn(m_vki->instance(), device), extensions, enabledFeatures);
Rc<DxvkDevice> result = new DxvkDevice(this,
new vk::DeviceFn(m_vki->instance(), device),
extensions, enabledFeatures);
result->initResources();
return result;
}

View File

@ -304,6 +304,17 @@ namespace dxvk {
m_vkd->vkCmdEndRenderPass(m_buffer);
}
void cmdFillBuffer(
VkBuffer dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize size,
uint32_t data) {
m_vkd->vkCmdFillBuffer(m_buffer,
dstBuffer, dstOffset, size, data);
}
void cmdPipelineBarrier(
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,

View File

@ -175,6 +175,32 @@ namespace dxvk {
}
void DxvkContext::clearBuffer(
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize length,
uint32_t value) {
this->renderPassEnd();
auto slice = buffer->subSlice(offset, length);
m_cmd->cmdFillBuffer(
slice.handle(),
slice.offset(),
slice.length(),
value);
m_barriers.accessBuffer(slice,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
buffer->info().stages,
buffer->info().access);
m_barriers.recordCommands(m_cmd);
m_cmd->trackResource(slice.resource());
}
void DxvkContext::clearColorImage(
const Rc<DxvkImage>& image,
const VkClearColorValue& value,

View File

@ -135,6 +135,23 @@ namespace dxvk {
const DxvkBufferSlice& buffer,
uint32_t stride);
/**
* \brief Clears a buffer with a fixed value
*
* Note that both \c offset and \c length must
* be multiples of four, and that \c value is
* consumed as a four-byte word.
* \param [in] buffer The buffer to clear
* \param [in] offset Offset of the range to clear
* \param [in] length Bumber of bytes to clear
* \param [in] value Clear value
*/
void clearBuffer(
const Rc<DxvkBuffer>& buffer,
VkDeviceSize offset,
VkDeviceSize length,
uint32_t value);
/**
* \brief Clears subresources of a color image
*

View File

@ -192,6 +192,11 @@ namespace dxvk {
}
void DxvkDevice::initResources() {
m_unboundResources.clearResources(this);
}
VkResult DxvkDevice::presentSwapImage(
const VkPresentInfoKHR& presentInfo) {
m_statCounters.increment(DxvkStat::DevQueuePresents, 1);

View File

@ -35,6 +35,7 @@ namespace dxvk {
* contexts. Multiple contexts can be created for a device.
*/
class DxvkDevice : public RcObject {
friend class DxvkContext;
friend class DxvkSubmissionQueue;
constexpr static VkDeviceSize DefaultStagingBufferSize = 4 * 1024 * 1024;
@ -276,46 +277,13 @@ namespace dxvk {
const DxvkSwapchainProperties& properties);
/**
* \brief Dummy buffer handle
* \returns Use for unbound vertex buffers.
*/
VkBuffer dummyBufferHandle() const {
return m_unboundResources.bufferHandle();
}
/**
* \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
* \brief Initializes dummy resources
*
* \param [in] type Required view type
* \returns Descriptor that points to a dummy image
* Should be called after creating the device in
* case the device initialization was successful
* and the device is usable.
*/
VkDescriptorImageInfo dummyImageViewDescriptor(VkImageViewType type) const {
return m_unboundResources.imageViewDescriptor(type);
}
void initResources();
/**
* \brief Presents a swap chain image
@ -379,7 +347,6 @@ namespace dxvk {
VkQueue m_graphicsQueue = VK_NULL_HANDLE;
VkQueue m_presentQueue = VK_NULL_HANDLE;
// TODO fine-tune buffer sizes
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
DxvkRecycler<DxvkStagingBuffer, 4> m_recycledStagingBuffers;
@ -390,6 +357,48 @@ namespace dxvk {
void recycleCommandList(
const Rc<DxvkCommandList>& cmdList);
/**
* \brief Dummy buffer handle
* \returns Use for unbound vertex buffers.
*/
VkBuffer dummyBufferHandle() const {
return m_unboundResources.bufferHandle();
}
/**
* \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);
}
};
}

View File

@ -25,6 +25,21 @@ namespace dxvk {
}
void DxvkUnboundResources::clearResources(DxvkDevice* dev) {
const Rc<DxvkContext> ctx = dev->createContext();
ctx->beginRecording(dev->createCommandList());
this->clearBuffer(ctx, m_buffer);
this->clearImage(ctx, m_image1D);
this->clearImage(ctx, m_image2D);
this->clearImage(ctx, m_image3D);
dev->submitCommandList(
ctx->endRecording(),
nullptr, nullptr);
}
Rc<DxvkSampler> DxvkUnboundResources::createSampler(DxvkDevice* dev) {
DxvkSamplerCreateInfo info;
info.minFilter = VK_FILTER_LINEAR;
@ -50,11 +65,13 @@ namespace dxvk {
Rc<DxvkBuffer> DxvkUnboundResources::createBuffer(DxvkDevice* dev) {
DxvkBufferCreateInfo info;
info.size = 4;
info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| 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
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| 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
@ -93,9 +110,11 @@ namespace dxvk {
info.extent = { 1, 1, 1 };
info.numLayers = layers;
info.mipLevels = 1;
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT
info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_SAMPLED_BIT
| VK_IMAGE_USAGE_STORAGE_BIT;
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| 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
@ -147,4 +166,23 @@ namespace dxvk {
}
}
void DxvkUnboundResources::clearBuffer(
const Rc<DxvkContext>& ctx,
const Rc<DxvkBuffer>& buffer) {
ctx->clearBuffer(buffer, 0, buffer->info().size, 0);
}
void DxvkUnboundResources::clearImage(
const Rc<DxvkContext>& ctx,
const Rc<DxvkImage>& image) {
ctx->clearColorImage(image,
VkClearColorValue { },
VkImageSubresourceRange {
VK_IMAGE_ASPECT_COLOR_BIT,
0, image->info().mipLevels,
0, image->info().numLayers });
}
}

View File

@ -35,8 +35,9 @@ namespace dxvk {
/**
* \brief Dummy buffer descriptor
*
* Points to a small buffer with undefined
* values. Do not access this buffer.
* Points to a small buffer filled with zeroes.
* Do not write to this buffer, and do not use
* it if out-of-bounds read access is possible.
* \returns Dummy buffer descriptor
*/
VkDescriptorBufferInfo bufferDescriptor() const {
@ -95,6 +96,14 @@ namespace dxvk {
return result;
}
/**
* \brief Clears the resources
*
* Initializes all images and buffers to zero.
* \param [in] dev The DXVK device handle
*/
void clearResources(DxvkDevice* dev);
private:
Rc<DxvkSampler> m_sampler;
@ -136,6 +145,14 @@ namespace dxvk {
const DxvkImageView* getImageView(
VkImageViewType type) const;
void clearBuffer(
const Rc<DxvkContext>& ctx,
const Rc<DxvkBuffer>& buffer);
void clearImage(
const Rc<DxvkContext>& ctx,
const Rc<DxvkImage>& image);
};
}