mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-04 16:24:29 +01:00
[dxvk] Add support for drawing a software cursor
This commit is contained in:
parent
4420c39b62
commit
329d9a0bb2
@ -443,7 +443,7 @@ namespace dxvk {
|
|||||||
cHud->render(contextObjects, cBackBuffer, cColorSpace);
|
cHud->render(contextObjects, cBackBuffer, cColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
cBlitter->endPresent(contextObjects, cBackBuffer);
|
cBlitter->endPresent(contextObjects, cBackBuffer, cColorSpace);
|
||||||
|
|
||||||
// Submit current command list and present
|
// Submit current command list and present
|
||||||
ctx->synchronizeWsi(cSync);
|
ctx->synchronizeWsi(cSync);
|
||||||
|
@ -880,7 +880,7 @@ namespace dxvk {
|
|||||||
cHud->render(contextObjects, cDstView, cColorSpace);
|
cHud->render(contextObjects, cDstView, cColorSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
cBlitter->endPresent(contextObjects, cDstView);
|
cBlitter->endPresent(contextObjects, cDstView, cColorSpace);
|
||||||
|
|
||||||
// Submit command list and present
|
// Submit command list and present
|
||||||
ctx->synchronizeWsi(cSync);
|
ctx->synchronizeWsi(cSync);
|
||||||
|
@ -63,6 +63,9 @@ namespace dxvk {
|
|||||||
if (m_gammaBuffer)
|
if (m_gammaBuffer)
|
||||||
uploadGammaImage(ctx);
|
uploadGammaImage(ctx);
|
||||||
|
|
||||||
|
if (m_cursorBuffer)
|
||||||
|
uploadCursorImage(ctx);
|
||||||
|
|
||||||
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
||||||
barrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
barrier.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
barrier.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
@ -99,85 +102,29 @@ namespace dxvk {
|
|||||||
|
|
||||||
ctx.cmd->cmdBeginRendering(&renderInfo);
|
ctx.cmd->cmdBeginRendering(&renderInfo);
|
||||||
|
|
||||||
DxvkSwapchainPipelineKey key;
|
performDraw(ctx,
|
||||||
key.srcSpace = srcColorSpace;
|
dstView, dstColorSpace, dstRect,
|
||||||
key.srcSamples = srcView->image()->info().sampleCount;
|
srcView, srcColorSpace, srcRect,
|
||||||
key.srcIsSrgb = srcView->formatInfo()->flags.test(DxvkFormatFlag::ColorSpaceSrgb);
|
VK_FALSE);
|
||||||
key.dstSpace = dstColorSpace;
|
|
||||||
key.dstFormat = dstView->info().format;
|
|
||||||
key.needsGamma = m_gammaView != nullptr;
|
|
||||||
key.needsBlit = dstRect.extent != srcRect.extent;
|
|
||||||
|
|
||||||
VkPipeline pipeline = getPipeline(key);
|
|
||||||
|
|
||||||
VkViewport viewport = { };
|
|
||||||
viewport.x = float(dstRect.offset.x);
|
|
||||||
viewport.y = float(dstRect.offset.y);
|
|
||||||
viewport.width = float(dstRect.extent.width);
|
|
||||||
viewport.height = float(dstRect.extent.height);
|
|
||||||
viewport.minDepth = 0.0f;
|
|
||||||
viewport.maxDepth = 0.0f;
|
|
||||||
|
|
||||||
ctx.cmd->cmdSetViewport(1, &viewport);
|
|
||||||
ctx.cmd->cmdSetScissor(1, &dstRect);
|
|
||||||
|
|
||||||
ctx.cmd->cmdBindPipeline(DxvkCmdBuffer::ExecBuffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
|
||||||
|
|
||||||
VkDescriptorSet set = ctx.descriptorPool->alloc(m_setLayout);
|
|
||||||
|
|
||||||
VkDescriptorImageInfo imageDescriptor = { };
|
|
||||||
imageDescriptor.sampler = m_samplerPresent->handle();
|
|
||||||
imageDescriptor.imageView = srcView->handle();
|
|
||||||
imageDescriptor.imageLayout = srcView->image()->info().layout;
|
|
||||||
|
|
||||||
VkDescriptorImageInfo gammaDescriptor = { };
|
|
||||||
gammaDescriptor.sampler = m_samplerGamma->handle();
|
|
||||||
|
|
||||||
if (m_gammaView) {
|
|
||||||
gammaDescriptor.imageView = m_gammaView->handle();
|
|
||||||
gammaDescriptor.imageLayout = m_gammaView->image()->info().layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<VkWriteDescriptorSet, 2> descriptorWrites = {{
|
|
||||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
|
||||||
set, 0, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptor },
|
|
||||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
|
||||||
set, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &gammaDescriptor },
|
|
||||||
}};
|
|
||||||
|
|
||||||
ctx.cmd->updateDescriptorSets(
|
|
||||||
descriptorWrites.size(), descriptorWrites.data());
|
|
||||||
ctx.cmd->cmdBindDescriptorSet(DxvkCmdBuffer::ExecBuffer,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout,
|
|
||||||
set, 0, nullptr);
|
|
||||||
|
|
||||||
PushConstants args = { };
|
|
||||||
args.srcOffset = srcRect.offset;
|
|
||||||
args.srcExtent = srcRect.extent;
|
|
||||||
args.dstOffset = dstRect.offset;
|
|
||||||
|
|
||||||
ctx.cmd->cmdPushConstants(DxvkCmdBuffer::ExecBuffer,
|
|
||||||
m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
||||||
0, sizeof(args), &args);
|
|
||||||
|
|
||||||
ctx.cmd->cmdDraw(3, 1, 0, 0);
|
|
||||||
|
|
||||||
// Make sure to keep used resources alive
|
|
||||||
ctx.cmd->trackResource<DxvkAccess::Read>(srcView->image());
|
|
||||||
ctx.cmd->trackResource<DxvkAccess::Write>(dstView->image());
|
|
||||||
|
|
||||||
if (m_gammaImage)
|
|
||||||
ctx.cmd->trackResource<DxvkAccess::Read>(m_gammaImage->getAllocation());
|
|
||||||
|
|
||||||
ctx.cmd->trackSampler(m_samplerGamma);
|
|
||||||
ctx.cmd->trackSampler(m_samplerPresent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkSwapchainBlitter::endPresent(
|
void DxvkSwapchainBlitter::endPresent(
|
||||||
const DxvkContextObjects& ctx,
|
const DxvkContextObjects& ctx,
|
||||||
const Rc<DxvkImageView>& dstView) {
|
const Rc<DxvkImageView>& dstView,
|
||||||
|
VkColorSpaceKHR dstColorSpace) {
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
|
||||||
|
if (m_cursorView) {
|
||||||
|
VkRect2D cursorArea = { };
|
||||||
|
cursorArea.extent.width = m_cursorImage->info().extent.width;
|
||||||
|
cursorArea.extent.height = m_cursorImage->info().extent.height;
|
||||||
|
|
||||||
|
performDraw(ctx, dstView, dstColorSpace, m_cursorRect,
|
||||||
|
m_cursorView, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, cursorArea,
|
||||||
|
VK_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.cmd->cmdEndRendering();
|
ctx.cmd->cmdEndRendering();
|
||||||
|
|
||||||
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
VkImageMemoryBarrier2 barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
||||||
@ -228,6 +175,182 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkSwapchainBlitter::setCursorTexture(
|
||||||
|
VkExtent2D extent,
|
||||||
|
VkFormat format,
|
||||||
|
const void* data) {
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
|
||||||
|
if (extent.width && extent.height && format && data) {
|
||||||
|
auto formatInfo = lookupFormatInfo(format);
|
||||||
|
|
||||||
|
DxvkBufferCreateInfo bufferInfo = { };
|
||||||
|
bufferInfo.size = extent.width * extent.height * formatInfo->elementSize;
|
||||||
|
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
|
||||||
|
m_cursorBuffer = m_device->createBuffer(bufferInfo,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
|
std::memcpy(m_cursorBuffer->mapPtr(0), data, bufferInfo.size);
|
||||||
|
|
||||||
|
DxvkImageCreateInfo imageInfo = { };
|
||||||
|
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||||
|
imageInfo.format = format;
|
||||||
|
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
imageInfo.extent = { extent.width, extent.height, 1u };
|
||||||
|
imageInfo.numLayers = 1u;
|
||||||
|
imageInfo.mipLevels = 1u;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||||
|
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
||||||
|
| VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
||||||
|
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
imageInfo.access = 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;
|
||||||
|
|
||||||
|
m_cursorImage = m_device->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
DxvkImageViewKey viewInfo = { };
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
viewInfo.format = format;
|
||||||
|
viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
viewInfo.mipIndex = 0u;
|
||||||
|
viewInfo.mipCount = 1u;
|
||||||
|
viewInfo.layerIndex = 0u;
|
||||||
|
viewInfo.layerCount = 1u;
|
||||||
|
|
||||||
|
m_cursorView = m_cursorImage->createView(viewInfo);
|
||||||
|
} else {
|
||||||
|
// Destroy cursor image
|
||||||
|
m_cursorBuffer = nullptr;
|
||||||
|
m_cursorImage = nullptr;
|
||||||
|
m_cursorView = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkSwapchainBlitter::setCursorPos(
|
||||||
|
VkRect2D rect) {
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
m_cursorRect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkSwapchainBlitter::performDraw(
|
||||||
|
const DxvkContextObjects& ctx,
|
||||||
|
const Rc<DxvkImageView>& dstView,
|
||||||
|
VkColorSpaceKHR dstColorSpace,
|
||||||
|
VkRect2D dstRect,
|
||||||
|
const Rc<DxvkImageView>& srcView,
|
||||||
|
VkColorSpaceKHR srcColorSpace,
|
||||||
|
VkRect2D srcRect,
|
||||||
|
VkBool32 enableBlending) {
|
||||||
|
VkExtent3D dstExtent = dstView->mipLevelExtent(0);
|
||||||
|
|
||||||
|
VkOffset2D coordA = dstRect.offset;
|
||||||
|
VkOffset2D coordB = {
|
||||||
|
coordA.x + int32_t(dstRect.extent.width),
|
||||||
|
coordA.y + int32_t(dstRect.extent.height)
|
||||||
|
};
|
||||||
|
|
||||||
|
coordA.x = std::max(coordA.x, 0);
|
||||||
|
coordA.y = std::max(coordA.y, 0);
|
||||||
|
coordB.x = std::min(coordB.x, int32_t(dstExtent.width));
|
||||||
|
coordB.y = std::min(coordB.y, int32_t(dstExtent.height));
|
||||||
|
|
||||||
|
if (coordA.x >= coordB.x || coordA.y >= coordB.y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VkViewport viewport = { };
|
||||||
|
viewport.x = float(dstRect.offset.x);
|
||||||
|
viewport.y = float(dstRect.offset.y);
|
||||||
|
viewport.width = float(dstRect.extent.width);
|
||||||
|
viewport.height = float(dstRect.extent.height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 0.0f;
|
||||||
|
|
||||||
|
ctx.cmd->cmdSetViewport(1, &viewport);
|
||||||
|
|
||||||
|
VkRect2D scissor = { };
|
||||||
|
scissor.offset = coordA;
|
||||||
|
scissor.extent.width = uint32_t(coordB.x - coordA.x);
|
||||||
|
scissor.extent.height = uint32_t(coordB.y - coordA.y);
|
||||||
|
|
||||||
|
ctx.cmd->cmdSetScissor(1, &scissor);
|
||||||
|
|
||||||
|
DxvkSwapchainPipelineKey key;
|
||||||
|
key.srcSpace = srcColorSpace;
|
||||||
|
key.srcSamples = srcView->image()->info().sampleCount;
|
||||||
|
key.srcIsSrgb = srcView->formatInfo()->flags.test(DxvkFormatFlag::ColorSpaceSrgb);
|
||||||
|
key.dstSpace = dstColorSpace;
|
||||||
|
key.dstFormat = dstView->info().format;
|
||||||
|
key.needsGamma = m_gammaView != nullptr;
|
||||||
|
key.needsBlit = dstRect.extent != srcRect.extent;
|
||||||
|
key.needsBlending = enableBlending;
|
||||||
|
|
||||||
|
VkPipeline pipeline = getPipeline(key);
|
||||||
|
|
||||||
|
ctx.cmd->cmdBindPipeline(DxvkCmdBuffer::ExecBuffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
|
||||||
|
VkDescriptorSet set = ctx.descriptorPool->alloc(m_setLayout);
|
||||||
|
|
||||||
|
VkDescriptorImageInfo imageDescriptor = { };
|
||||||
|
imageDescriptor.sampler = m_samplerPresent->handle();
|
||||||
|
imageDescriptor.imageView = srcView->handle();
|
||||||
|
imageDescriptor.imageLayout = srcView->image()->info().layout;
|
||||||
|
|
||||||
|
VkDescriptorImageInfo gammaDescriptor = { };
|
||||||
|
gammaDescriptor.sampler = m_samplerGamma->handle();
|
||||||
|
|
||||||
|
if (m_gammaView) {
|
||||||
|
gammaDescriptor.imageView = m_gammaView->handle();
|
||||||
|
gammaDescriptor.imageLayout = m_gammaView->image()->info().layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<VkWriteDescriptorSet, 2> descriptorWrites = {{
|
||||||
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||||
|
set, 0, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptor },
|
||||||
|
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr,
|
||||||
|
set, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &gammaDescriptor },
|
||||||
|
}};
|
||||||
|
|
||||||
|
ctx.cmd->updateDescriptorSets(
|
||||||
|
descriptorWrites.size(), descriptorWrites.data());
|
||||||
|
|
||||||
|
ctx.cmd->cmdBindDescriptorSet(DxvkCmdBuffer::ExecBuffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout,
|
||||||
|
set, 0, nullptr);
|
||||||
|
|
||||||
|
PushConstants args = { };
|
||||||
|
args.srcOffset = srcRect.offset;
|
||||||
|
args.srcExtent = srcRect.extent;
|
||||||
|
args.dstOffset = dstRect.offset;
|
||||||
|
|
||||||
|
ctx.cmd->cmdPushConstants(DxvkCmdBuffer::ExecBuffer,
|
||||||
|
m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0, sizeof(args), &args);
|
||||||
|
|
||||||
|
ctx.cmd->cmdDraw(3, 1, 0, 0);
|
||||||
|
|
||||||
|
// Make sure to keep used resources alive
|
||||||
|
ctx.cmd->trackResource<DxvkAccess::Read>(srcView->image());
|
||||||
|
ctx.cmd->trackResource<DxvkAccess::Write>(dstView->image());
|
||||||
|
|
||||||
|
if (m_gammaImage)
|
||||||
|
ctx.cmd->trackResource<DxvkAccess::Read>(m_gammaImage->getAllocation());
|
||||||
|
|
||||||
|
ctx.cmd->trackSampler(m_samplerGamma);
|
||||||
|
ctx.cmd->trackSampler(m_samplerPresent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkSwapchainBlitter::uploadGammaImage(
|
void DxvkSwapchainBlitter::uploadGammaImage(
|
||||||
const DxvkContextObjects& ctx) {
|
const DxvkContextObjects& ctx) {
|
||||||
if (!m_gammaImage || m_gammaImage->info().extent.width != m_gammaCpCount) {
|
if (!m_gammaImage || m_gammaImage->info().extent.width != m_gammaCpCount) {
|
||||||
@ -266,6 +389,13 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkSwapchainBlitter::uploadCursorImage(
|
||||||
|
const DxvkContextObjects& ctx) {
|
||||||
|
uploadTexture(ctx, m_cursorImage, m_cursorBuffer);
|
||||||
|
m_cursorBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkSwapchainBlitter::uploadTexture(
|
void DxvkSwapchainBlitter::uploadTexture(
|
||||||
const DxvkContextObjects& ctx,
|
const DxvkContextObjects& ctx,
|
||||||
const Rc<DxvkImage>& image,
|
const Rc<DxvkImage>& image,
|
||||||
|
@ -114,10 +114,12 @@ namespace dxvk {
|
|||||||
* Finishes rendering and prepares the image for presentation.
|
* Finishes rendering and prepares the image for presentation.
|
||||||
* \param [in] ctx Context objects
|
* \param [in] ctx Context objects
|
||||||
* \param [in] dstView Swap chain image view
|
* \param [in] dstView Swap chain image view
|
||||||
|
* \param [in] dstColorSpace Swap chain color space
|
||||||
*/
|
*/
|
||||||
void endPresent(
|
void endPresent(
|
||||||
const DxvkContextObjects& ctx,
|
const DxvkContextObjects& ctx,
|
||||||
const Rc<DxvkImageView>& dstView);
|
const Rc<DxvkImageView>& dstView,
|
||||||
|
VkColorSpaceKHR dstColorSpace);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Sets gamma ramp
|
* \brief Sets gamma ramp
|
||||||
@ -132,6 +134,30 @@ namespace dxvk {
|
|||||||
uint32_t cpCount,
|
uint32_t cpCount,
|
||||||
const DxvkGammaCp* cpData);
|
const DxvkGammaCp* cpData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets software cursor texture
|
||||||
|
*
|
||||||
|
* The cursor image is assumed to be in sRGB color space.
|
||||||
|
* \param [in] extent Texture size, in pixels
|
||||||
|
* \param [in] format Texture format
|
||||||
|
* \param [in] data Texture data. Assumed to be
|
||||||
|
* tightly packed according to the format.
|
||||||
|
*/
|
||||||
|
void setCursorTexture(
|
||||||
|
VkExtent2D extent,
|
||||||
|
VkFormat format,
|
||||||
|
const void* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets cursor position
|
||||||
|
*
|
||||||
|
* If the size does not match the texture size, the
|
||||||
|
* cursor will be rendered with a linear filter.
|
||||||
|
* \param [in] rect Cursor rectangle, in pixels
|
||||||
|
*/
|
||||||
|
void setCursorPos(
|
||||||
|
VkRect2D rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct SpecConstants {
|
struct SpecConstants {
|
||||||
@ -168,6 +194,11 @@ namespace dxvk {
|
|||||||
Rc<DxvkImageView> m_gammaView;
|
Rc<DxvkImageView> m_gammaView;
|
||||||
uint32_t m_gammaCpCount = 0;
|
uint32_t m_gammaCpCount = 0;
|
||||||
|
|
||||||
|
Rc<DxvkBuffer> m_cursorBuffer;
|
||||||
|
Rc<DxvkImage> m_cursorImage;
|
||||||
|
Rc<DxvkImageView> m_cursorView;
|
||||||
|
VkRect2D m_cursorRect = { };
|
||||||
|
|
||||||
Rc<DxvkSampler> m_samplerPresent;
|
Rc<DxvkSampler> m_samplerPresent;
|
||||||
Rc<DxvkSampler> m_samplerGamma;
|
Rc<DxvkSampler> m_samplerGamma;
|
||||||
|
|
||||||
@ -177,6 +208,16 @@ namespace dxvk {
|
|||||||
std::unordered_map<DxvkSwapchainPipelineKey,
|
std::unordered_map<DxvkSwapchainPipelineKey,
|
||||||
VkPipeline, DxvkHash, DxvkEq> m_pipelines;
|
VkPipeline, DxvkHash, DxvkEq> m_pipelines;
|
||||||
|
|
||||||
|
void performDraw(
|
||||||
|
const DxvkContextObjects& ctx,
|
||||||
|
const Rc<DxvkImageView>& dstView,
|
||||||
|
VkColorSpaceKHR dstColorSpace,
|
||||||
|
VkRect2D dstRect,
|
||||||
|
const Rc<DxvkImageView>& srcView,
|
||||||
|
VkColorSpaceKHR srcColorSpace,
|
||||||
|
VkRect2D srcRect,
|
||||||
|
VkBool32 enableBlending);
|
||||||
|
|
||||||
void uploadGammaImage(
|
void uploadGammaImage(
|
||||||
const DxvkContextObjects& ctx);
|
const DxvkContextObjects& ctx);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user