mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 01:24:11 +01:00
[dxvk] Implemented support for multisampled images and render targets
This commit is contained in:
parent
de47fa29e1
commit
5f0e94138e
@ -156,10 +156,22 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxgiPresenter::presentImage(const Rc<DxvkImageView>& view) {
|
||||
void DxgiPresenter::presentImage() {
|
||||
m_context->beginRecording(
|
||||
m_device->createCommandList());
|
||||
|
||||
VkImageSubresourceLayers resolveSubresources;
|
||||
resolveSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveSubresources.mipLevel = 0;
|
||||
resolveSubresources.baseArrayLayer = 0;
|
||||
resolveSubresources.layerCount = 1;
|
||||
|
||||
if (m_backBufferResolve != nullptr) {
|
||||
m_context->resolveImage(
|
||||
m_backBufferResolve, resolveSubresources,
|
||||
m_backBuffer, resolveSubresources);
|
||||
}
|
||||
|
||||
auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync);
|
||||
auto framebufferSize = framebuffer->size();
|
||||
|
||||
@ -186,7 +198,7 @@ namespace dxvk {
|
||||
BindingIds::Sampler, m_sampler);
|
||||
m_context->bindResourceImage(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
BindingIds::Texture, view);
|
||||
BindingIds::Texture, m_backBufferView);
|
||||
m_context->draw(4, 1, 0, 0);
|
||||
|
||||
m_device->submitCommandList(
|
||||
@ -201,6 +213,108 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkImage> DxgiPresenter::createBackBuffer(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
VkFormat bufferFormat,
|
||||
VkSampleCountFlagBits sampleCount) {
|
||||
Logger::info(str::format("DxgiPresenter: Creating back buffer with ", bufferFormat));
|
||||
|
||||
// Explicitly destroy the old stuff
|
||||
m_backBuffer = nullptr;
|
||||
m_backBufferResolve = nullptr;
|
||||
m_backBufferView = nullptr;
|
||||
|
||||
// Create an image that can be rendered to
|
||||
// and that can be used as a sampled texture.
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = bufferFormat;
|
||||
imageInfo.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
imageInfo.sampleCount = sampleCount;
|
||||
imageInfo.extent.width = bufferWidth;
|
||||
imageInfo.extent.height = bufferHeight;
|
||||
imageInfo.extent.depth = 1;
|
||||
imageInfo.numLayers = 1;
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
imageInfo.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_TRANSFER_READ_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
if (m_device->features().geometryShader)
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
|
||||
if (m_device->features().tessellationShader) {
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
|
||||
m_backBuffer = m_device->createImage(imageInfo,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
// If a multisampled back buffer was requested, we also need to
|
||||
// create a resolve image with otherwise identical properties.
|
||||
// Multisample images cannot be sampled from.
|
||||
if (sampleCount != VK_SAMPLE_COUNT_1_BIT) {
|
||||
DxvkImageCreateInfo resolveInfo;
|
||||
resolveInfo.type = VK_IMAGE_TYPE_2D;
|
||||
resolveInfo.format = bufferFormat;
|
||||
resolveInfo.flags = 0;
|
||||
resolveInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
resolveInfo.extent.width = bufferWidth;
|
||||
resolveInfo.extent.height = bufferHeight;
|
||||
resolveInfo.extent.depth = 1;
|
||||
resolveInfo.numLayers = 1;
|
||||
resolveInfo.mipLevels = 1;
|
||||
resolveInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
resolveInfo.stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
resolveInfo.access = VK_ACCESS_SHADER_READ_BIT
|
||||
| VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
resolveInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
resolveInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
m_backBufferResolve = m_device->createImage(
|
||||
resolveInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
}
|
||||
|
||||
// Create an image view that allows the
|
||||
// image to be bound as a shader resource.
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = imageInfo.format;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = 1;
|
||||
|
||||
m_backBufferView = m_device->createImageView(
|
||||
m_backBufferResolve != nullptr
|
||||
? m_backBufferResolve
|
||||
: m_backBuffer,
|
||||
viewInfo);
|
||||
|
||||
// TODO move this elsewhere
|
||||
this->initBackBuffer(m_backBuffer);
|
||||
return m_backBuffer;
|
||||
}
|
||||
|
||||
|
||||
void DxgiPresenter::recreateSwapchain(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
|
@ -29,7 +29,7 @@ namespace dxvk {
|
||||
DXGI_FORMAT bufferFormat);
|
||||
|
||||
~DxgiPresenter();
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initializes back buffer image
|
||||
* \param [in] image Back buffer image
|
||||
@ -38,20 +38,32 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image);
|
||||
|
||||
/**
|
||||
* \brief Renders image to the screen
|
||||
* \param [in] view Source image view
|
||||
* \brief Renders back buffer to the screen
|
||||
*/
|
||||
void presentImage(
|
||||
const Rc<DxvkImageView>& view);
|
||||
void presentImage();
|
||||
|
||||
/**
|
||||
* \brief Recreates back buffer
|
||||
*
|
||||
* \param [in] bufferWidth Buffer width
|
||||
* \param [in] bufferHeight Buffer height
|
||||
* \param [in] bufferFormat Buffer format
|
||||
* \returns Back buffer image
|
||||
*/
|
||||
Rc<DxvkImage> createBackBuffer(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
VkFormat bufferFormat,
|
||||
VkSampleCountFlagBits sampleCount);
|
||||
|
||||
/**
|
||||
* \brief Renders image to the screen
|
||||
* \param [in] view Source image view
|
||||
*/
|
||||
void recreateSwapchain(
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat);
|
||||
uint32_t bufferWidth,
|
||||
uint32_t bufferHeight,
|
||||
DXGI_FORMAT bufferFormat);
|
||||
|
||||
private:
|
||||
|
||||
@ -71,6 +83,10 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkSampler> m_sampler;
|
||||
|
||||
Rc<DxvkImage> m_backBuffer;
|
||||
Rc<DxvkImage> m_backBufferResolve;
|
||||
Rc<DxvkImageView> m_backBufferView;
|
||||
|
||||
VkSurfaceFormatKHR pickFormat(DXGI_FORMAT fmt) const;
|
||||
|
||||
Rc<DxvkShader> createVertexShader();
|
||||
|
@ -2,6 +2,15 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxgiImageResource::DxgiImageResource(
|
||||
IDXGIDevicePrivate* pDevice,
|
||||
const Rc<DxvkImage>& image,
|
||||
UINT usageFlags)
|
||||
: Base(pDevice, usageFlags), m_image(image) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxgiImageResource::DxgiImageResource(
|
||||
IDXGIDevicePrivate* pDevice,
|
||||
const dxvk::DxvkImageCreateInfo* pCreateInfo,
|
||||
|
@ -68,6 +68,11 @@ namespace dxvk {
|
||||
using Base = DxgiResource<IDXGIImageResourcePrivate>;
|
||||
public:
|
||||
|
||||
DxgiImageResource(
|
||||
IDXGIDevicePrivate* pDevice,
|
||||
const Rc<DxvkImage>& image,
|
||||
UINT usageFlags);
|
||||
|
||||
DxgiImageResource(
|
||||
IDXGIDevicePrivate* pDevice,
|
||||
const dxvk::DxvkImageCreateInfo* pCreateInfo,
|
||||
|
@ -59,10 +59,12 @@ namespace dxvk {
|
||||
|
||||
this->createPresenter();
|
||||
this->createBackBuffer();
|
||||
TRACE(this);
|
||||
}
|
||||
|
||||
|
||||
DxgiSwapChain::~DxgiSwapChain() {
|
||||
TRACE(this);
|
||||
// We do not release the SDL window handle here since
|
||||
// that would destroy the underlying window as well.
|
||||
}
|
||||
@ -177,7 +179,7 @@ namespace dxvk {
|
||||
|
||||
// TODO implement sync interval
|
||||
// TODO implement flags
|
||||
m_presenter->presentImage(m_backBufferView);
|
||||
m_presenter->presentImage();
|
||||
return S_OK;
|
||||
} catch (const DxvkError& err) {
|
||||
Logger::err(err.message());
|
||||
@ -322,80 +324,24 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxgiSwapChain::createBackBuffer() {
|
||||
// Pick the back buffer format based on the requested swap chain format
|
||||
DxgiFormatPair bufferFormat = m_adapter->LookupFormat(m_desc.BufferDesc.Format);
|
||||
Logger::info(str::format("DxgiSwapChain: Creating back buffer with ", bufferFormat.actual));
|
||||
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
// TODO support proper multi-sampling
|
||||
const Rc<DxvkDevice> dxvkDevice = m_device->GetDXVKDevice();
|
||||
if (FAILED(GetSampleCount(m_desc.SampleDesc.Count, &sampleCount)))
|
||||
throw DxvkError("DxgiSwapChain::createBackBuffer: Invalid sample count");
|
||||
|
||||
// Create an image that can be rendered to
|
||||
// and that can be used as a sampled texture.
|
||||
Com<IDXGIImageResourcePrivate> resource;
|
||||
const Rc<DxvkImage> backBuffer = m_presenter->createBackBuffer(
|
||||
m_desc.BufferDesc.Width, m_desc.BufferDesc.Height,
|
||||
m_adapter->LookupFormat(m_desc.BufferDesc.Format).actual,
|
||||
sampleCount);
|
||||
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = bufferFormat.actual;
|
||||
imageInfo.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
|
||||
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.extent.width = m_desc.BufferDesc.Width;
|
||||
imageInfo.extent.height = m_desc.BufferDesc.Height;
|
||||
imageInfo.extent.depth = 1;
|
||||
imageInfo.numLayers = 1;
|
||||
imageInfo.mipLevels = 1;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
imageInfo.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
imageInfo.access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
|
||||
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
||||
| VK_ACCESS_TRANSFER_WRITE_BIT
|
||||
| VK_ACCESS_TRANSFER_READ_BIT
|
||||
| VK_ACCESS_SHADER_READ_BIT;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
if (dxvkDevice->features().geometryShader)
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
|
||||
if (dxvkDevice->features().tessellationShader) {
|
||||
imageInfo.stages |= VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||
}
|
||||
|
||||
if (FAILED(DXGICreateImageResourcePrivate(m_device.ptr(), &imageInfo,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, DXGI_USAGE_BACK_BUFFER | m_desc.BufferUsage,
|
||||
&resource)))
|
||||
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer");
|
||||
|
||||
m_backBuffer = resource->GetDXVKImage();
|
||||
|
||||
// Create an image view that allows the
|
||||
// image to be bound as a shader resource.
|
||||
DxvkImageViewCreateInfo viewInfo;
|
||||
viewInfo.type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = imageInfo.format;
|
||||
viewInfo.aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.minLevel = 0;
|
||||
viewInfo.numLevels = 1;
|
||||
viewInfo.minLayer = 0;
|
||||
viewInfo.numLayers = 1;
|
||||
|
||||
m_backBufferView = dxvkDevice->createImageView(m_backBuffer, viewInfo);
|
||||
const Com<IDXGIImageResourcePrivate> resource
|
||||
= new DxgiImageResource(m_device.ptr(), backBuffer,
|
||||
DXGI_USAGE_BACK_BUFFER | m_desc.BufferUsage);
|
||||
|
||||
// Wrap the back buffer image into an interface
|
||||
// that the device can use to access the image.
|
||||
if (FAILED(m_presentDevice->WrapSwapChainBackBuffer(resource.ptr(), &m_desc, &m_backBufferIface)))
|
||||
throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer interface");
|
||||
|
||||
// Initialize the image properly so that
|
||||
// it can be used in a DXVK context
|
||||
m_presenter->initBackBuffer(m_backBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -411,4 +357,17 @@ namespace dxvk {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetSampleCount(UINT Count, VkSampleCountFlagBits* pCount) const {
|
||||
switch (Count) {
|
||||
case 1: *pCount = VK_SAMPLE_COUNT_1_BIT; return S_OK;
|
||||
case 2: *pCount = VK_SAMPLE_COUNT_2_BIT; return S_OK;
|
||||
case 4: *pCount = VK_SAMPLE_COUNT_4_BIT; return S_OK;
|
||||
case 8: *pCount = VK_SAMPLE_COUNT_8_BIT; return S_OK;
|
||||
case 16: *pCount = VK_SAMPLE_COUNT_16_BIT; return S_OK;
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,9 +94,6 @@ namespace dxvk {
|
||||
SDL_Window* m_window = nullptr;
|
||||
|
||||
Rc<DxgiPresenter> m_presenter;
|
||||
|
||||
Rc<DxvkImage> m_backBuffer;
|
||||
Rc<DxvkImageView> m_backBufferView;
|
||||
Com<IUnknown> m_backBufferIface;
|
||||
|
||||
void createPresenter();
|
||||
@ -105,6 +102,10 @@ namespace dxvk {
|
||||
void createContext();
|
||||
|
||||
VkExtent2D getWindowSize() const;
|
||||
|
||||
HRESULT GetSampleCount(
|
||||
UINT Count,
|
||||
VkSampleCountFlagBits* pCount) const;
|
||||
|
||||
};
|
||||
|
||||
|
@ -274,6 +274,20 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::cmdResolveImage(
|
||||
VkImage srcImage,
|
||||
VkImageLayout srcImageLayout,
|
||||
VkImage dstImage,
|
||||
VkImageLayout dstImageLayout,
|
||||
uint32_t regionCount,
|
||||
const VkImageResolve* pRegions) {
|
||||
m_vkd->vkCmdResolveImage(m_buffer,
|
||||
srcImage, srcImageLayout,
|
||||
dstImage, dstImageLayout,
|
||||
regionCount, pRegions);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::cmdUpdateBuffer(
|
||||
VkBuffer dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
|
@ -163,6 +163,14 @@ namespace dxvk {
|
||||
uint32_t imageMemoryBarrierCount,
|
||||
const VkImageMemoryBarrier* pImageMemoryBarriers);
|
||||
|
||||
void cmdResolveImage(
|
||||
VkImage srcImage,
|
||||
VkImageLayout srcImageLayout,
|
||||
VkImage dstImage,
|
||||
VkImageLayout dstImageLayout,
|
||||
uint32_t regionCount,
|
||||
const VkImageResolve* pRegions);
|
||||
|
||||
void cmdUpdateBuffer(
|
||||
VkBuffer dstBuffer,
|
||||
VkDeviceSize dstOffset,
|
||||
|
@ -129,7 +129,7 @@ namespace dxvk {
|
||||
|
||||
if (image != nullptr) {
|
||||
descriptor.image.imageView = image->handle();
|
||||
descriptor.image.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
descriptor.image.imageLayout = image->imageInfo().layout;
|
||||
}
|
||||
|
||||
rc->bindShaderResource(slot, resource, descriptor);
|
||||
@ -368,6 +368,77 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::resolveImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources) {
|
||||
VkImageSubresourceRange dstSubresourceRange = {
|
||||
dstSubresources.aspectMask,
|
||||
dstSubresources.mipLevel, 1,
|
||||
dstSubresources.baseArrayLayer,
|
||||
dstSubresources.layerCount,
|
||||
};
|
||||
|
||||
VkImageSubresourceRange srcSubresourceRange = {
|
||||
srcSubresources.aspectMask,
|
||||
srcSubresources.mipLevel, 1,
|
||||
srcSubresources.baseArrayLayer,
|
||||
srcSubresources.layerCount,
|
||||
};
|
||||
|
||||
// We only support resolving to the entire image
|
||||
// area, so we might as well discard its contents
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, 0, 0,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
|
||||
VkImageResolve imageRegion;
|
||||
imageRegion.srcSubresource = srcSubresources;
|
||||
imageRegion.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
imageRegion.dstSubresource = dstSubresources;
|
||||
imageRegion.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
imageRegion.extent = srcImage->mipLevelExtent(srcSubresources.mipLevel);
|
||||
|
||||
m_cmd->cmdResolveImage(
|
||||
srcImage->handle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
dstImage->handle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &imageRegion);
|
||||
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dstImage->info().layout,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateBuffer(
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize offset,
|
||||
@ -718,7 +789,7 @@ namespace dxvk {
|
||||
gpState.rsViewportCount = m_state.vp.viewportCount;
|
||||
|
||||
// TODO implement multisampling support properly
|
||||
gpState.msSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
gpState.msSampleCount = m_state.om.framebuffer->sampleCount();
|
||||
gpState.msSampleMask = m_state.ms.sampleMask;
|
||||
gpState.msEnableAlphaToCoverage = m_state.ms.enableAlphaToCoverage;
|
||||
gpState.msEnableAlphaToOne = m_state.ms.enableAlphaToOne;
|
||||
|
@ -247,6 +247,23 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const VkImageSubresourceRange& subresources);
|
||||
|
||||
/**
|
||||
* \brief Resolves a multisampled image resource
|
||||
*
|
||||
* Resolves a multisampled image into a non-multisampled
|
||||
* image. The subresources of both images must have the
|
||||
* same size and compatible formats
|
||||
* \param [in] dstImage Destination image
|
||||
* \param [in] dstSubresources Subresources to write to
|
||||
* \param [in] srcImage Source image
|
||||
* \param [in] srcSubresources Subresources to read from
|
||||
*/
|
||||
void resolveImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources);
|
||||
|
||||
/**
|
||||
* \brief Updates a buffer
|
||||
*
|
||||
|
@ -155,6 +155,14 @@ namespace dxvk {
|
||||
return m_renderTargets;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sample count
|
||||
* \returns Sample count
|
||||
*/
|
||||
VkSampleCountFlagBits sampleCount() const {
|
||||
return m_renderPass->sampleCount();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
@ -123,6 +123,14 @@ namespace dxvk {
|
||||
return m_renderPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Render pass sample count
|
||||
* \returns Render pass sample count
|
||||
*/
|
||||
VkSampleCountFlagBits sampleCount() const {
|
||||
return m_format.getSampleCount();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
|
Loading…
Reference in New Issue
Block a user