renderer_vulkan: Transition swapchain manually
This commit is contained in:
@ -56,8 +56,7 @@ layout (std140, push_constant) uniform PresentUniformData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
//color = texture(sampler2D(top_screen, screen_sampler), frag_tex_coord);
|
color = texture(sampler2D(top_screen, screen_sampler), frag_tex_coord);
|
||||||
color = vec4(1.f, 0.f, 0.f, 1.f);
|
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
@ -159,7 +158,7 @@ DisplayRenderer::DisplayRenderer(Frontend::EmuWindow& window) : render_window(wi
|
|||||||
|
|
||||||
// Create vertex buffer for the screen rectangle
|
// Create vertex buffer for the screen rectangle
|
||||||
const BufferInfo vertex_info = {
|
const BufferInfo vertex_info = {
|
||||||
.capacity = sizeof(ScreenRectVertex) * 16,
|
.capacity = sizeof(ScreenRectVertex) * 4 * 4,
|
||||||
.usage = BufferUsage::Vertex
|
.usage = BufferUsage::Vertex
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -179,6 +178,11 @@ DisplayRenderer::DisplayRenderer(Frontend::EmuWindow& window) : render_window(wi
|
|||||||
// Set topology to strip
|
// Set topology to strip
|
||||||
present_pipeline_info.rasterization.topology.Assign(Pica::TriangleTopology::Strip);
|
present_pipeline_info.rasterization.topology.Assign(Pica::TriangleTopology::Strip);
|
||||||
|
|
||||||
|
// Disable blending, depth and stencil tests
|
||||||
|
present_pipeline_info.blending.blend_enable.Assign(0);
|
||||||
|
present_pipeline_info.depth_stencil.depth_test_enable.Assign(0);
|
||||||
|
present_pipeline_info.depth_stencil.stencil_test_enable.Assign(0);
|
||||||
|
|
||||||
// Create screen sampler
|
// Create screen sampler
|
||||||
const SamplerInfo sampler_info = {
|
const SamplerInfo sampler_info = {
|
||||||
.mag_filter = Pica::TextureFilter::Linear,
|
.mag_filter = Pica::TextureFilter::Linear,
|
||||||
|
@ -104,6 +104,11 @@ bool Backend::BeginPresent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Backend::EndPresent() {
|
void Backend::EndPresent() {
|
||||||
|
// Transition swapchain image to present layout
|
||||||
|
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
||||||
|
swapchain.GetCurrentImage()->Transition(command_buffer, vk::ImageLayout::ePresentSrcKHR);
|
||||||
|
|
||||||
|
// Submit and present
|
||||||
scheduler.Submit(false, true, swapchain.GetAvailableSemaphore(), swapchain.GetPresentSemaphore());
|
scheduler.Submit(false, true, swapchain.GetAvailableSemaphore(), swapchain.GetPresentSemaphore());
|
||||||
swapchain.Present();
|
swapchain.Present();
|
||||||
}
|
}
|
||||||
|
@ -198,12 +198,11 @@ Pipeline::Pipeline(Instance& instance, CommandScheduler& scheduler, PoolManager&
|
|||||||
for (int i = 0; i < info.shaders.size(); i++) {
|
for (int i = 0; i < info.shaders.size(); i++) {
|
||||||
auto& shader = info.shaders[i];
|
auto& shader = info.shaders[i];
|
||||||
if (!shader.IsValid()) {
|
if (!shader.IsValid()) {
|
||||||
shader_count = i;
|
continue;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader* vk_shader = static_cast<Shader*>(shader.Get());
|
Shader* vk_shader = static_cast<Shader*>(shader.Get());
|
||||||
shader_stages[i] = vk::PipelineShaderStageCreateInfo{
|
shader_stages[shader_count++] = vk::PipelineShaderStageCreateInfo{
|
||||||
.stage = ToVkShaderStage(shader->GetStage()),
|
.stage = ToVkShaderStage(shader->GetStage()),
|
||||||
.module = vk_shader->GetHandle(),
|
.module = vk_shader->GetHandle(),
|
||||||
.pName = "main"
|
.pName = "main"
|
||||||
@ -389,10 +388,15 @@ void Pipeline::Free() {
|
|||||||
void Pipeline::BindTexture(u32 group, u32 slot, TextureHandle handle) {
|
void Pipeline::BindTexture(u32 group, u32 slot, TextureHandle handle) {
|
||||||
Texture* texture = static_cast<Texture*>(handle.Get());
|
Texture* texture = static_cast<Texture*>(handle.Get());
|
||||||
|
|
||||||
|
// NOTE: To prevent validation errors when using the image without uploading
|
||||||
|
// transition it now to VK_IMAGE_LAYOUT_SHADER_READONLY_OPTIMAL
|
||||||
|
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
||||||
|
texture->Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
|
|
||||||
const DescriptorData data = {
|
const DescriptorData data = {
|
||||||
.image_info = vk::DescriptorImageInfo{
|
.image_info = vk::DescriptorImageInfo{
|
||||||
.imageView = texture->GetView(),
|
.imageView = texture->GetView(),
|
||||||
.imageLayout = texture->GetLayout()
|
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ void RenderpassCache::CreatePresentRenderpass(vk::Format format) {
|
|||||||
if (!present_renderpass) {
|
if (!present_renderpass) {
|
||||||
present_renderpass = CreateRenderPass(format, vk::Format::eUndefined,
|
present_renderpass = CreateRenderPass(format, vk::Format::eUndefined,
|
||||||
vk::AttachmentLoadOp::eClear,
|
vk::AttachmentLoadOp::eClear,
|
||||||
vk::ImageLayout::eUndefined,
|
vk::ImageLayout::eColorAttachmentOptimal,
|
||||||
vk::ImageLayout::ePresentSrcKHR);
|
vk::ImageLayout::eColorAttachmentOptimal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
#include "video_core/common/pool_manager.h"
|
#include "video_core/common/pool_manager.h"
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_backend.h"
|
|
||||||
#include "video_core/renderer_vulkan/vk_framebuffer.h"
|
#include "video_core/renderer_vulkan/vk_framebuffer.h"
|
||||||
#include "video_core/renderer_vulkan/vk_texture.h"
|
#include "video_core/renderer_vulkan/vk_texture.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||||
|
|
||||||
namespace VideoCore::Vulkan {
|
namespace VideoCore::Vulkan {
|
||||||
|
|
||||||
@ -167,6 +167,15 @@ void Swapchain::Present() {
|
|||||||
current_frame = (current_frame + 1) % vk_images.size();
|
current_frame = (current_frame + 1) % vk_images.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FramebufferHandle Swapchain::GetCurrentFramebuffer() {
|
||||||
|
return framebuffers[current_image];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the current swapchain image
|
||||||
|
Texture* Swapchain::GetCurrentImage() {
|
||||||
|
return static_cast<Texture*>(textures[current_image].Get());
|
||||||
|
}
|
||||||
|
|
||||||
void Swapchain::Configure(u32 width, u32 height) {
|
void Swapchain::Configure(u32 width, u32 height) {
|
||||||
vk::PhysicalDevice physical = instance.GetPhysicalDevice();
|
vk::PhysicalDevice physical = instance.GetPhysicalDevice();
|
||||||
|
|
||||||
|
@ -16,10 +16,10 @@ class PoolManager;
|
|||||||
namespace VideoCore::Vulkan {
|
namespace VideoCore::Vulkan {
|
||||||
|
|
||||||
class Instance;
|
class Instance;
|
||||||
class Backend;
|
|
||||||
class CommandScheduler;
|
class CommandScheduler;
|
||||||
class Texture;
|
|
||||||
class RenderpassCache;
|
class RenderpassCache;
|
||||||
|
class Texture;
|
||||||
|
class Framebuffer;
|
||||||
|
|
||||||
class Swapchain {
|
class Swapchain {
|
||||||
public:
|
public:
|
||||||
@ -36,9 +36,11 @@ public:
|
|||||||
// Presents the current image and move to the next one
|
// Presents the current image and move to the next one
|
||||||
void Present();
|
void Present();
|
||||||
|
|
||||||
FramebufferHandle GetCurrentFramebuffer() const {
|
// Returns the framebuffer the current image is attached to
|
||||||
return framebuffers[current_image];
|
FramebufferHandle GetCurrentFramebuffer();
|
||||||
}
|
|
||||||
|
// Returns the current swapchain image
|
||||||
|
Texture* GetCurrentImage();
|
||||||
|
|
||||||
// Returns current swapchain state
|
// Returns current swapchain state
|
||||||
vk::Extent2D GetExtent() const {
|
vk::Extent2D GetExtent() const {
|
||||||
@ -70,11 +72,6 @@ public:
|
|||||||
return render_finished;
|
return render_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current swapchain image
|
|
||||||
vk::Image GetCurrentImage() {
|
|
||||||
return vk_images[current_image];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true when the swapchain should be recreated
|
// Returns true when the swapchain should be recreated
|
||||||
bool NeedsRecreation() const {
|
bool NeedsRecreation() const {
|
||||||
return is_suboptimal || is_outdated;
|
return is_suboptimal || is_outdated;
|
||||||
|
@ -123,8 +123,7 @@ void CommandScheduler::Submit(bool wait_completion, bool begin_next,
|
|||||||
command.upload_command_buffer.end();
|
command.upload_command_buffer.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::array<vk::PipelineStageFlags, 2> wait_stage_masks{
|
const std::array<vk::PipelineStageFlags, 1> wait_stage_masks = {
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
|
||||||
vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,11 +122,6 @@ Texture::Texture(Instance& instance, CommandScheduler& scheduler, PoolManager& p
|
|||||||
|
|
||||||
// Create image view
|
// Create image view
|
||||||
image_view = device.createImageView(view_info);
|
image_view = device.createImageView(view_info);
|
||||||
|
|
||||||
// NOTE: To prevent validation errors when using the image without uploading
|
|
||||||
// transition it now to VK_IMAGE_LAYOUT_SHADER_READONLY_OPTIMAL
|
|
||||||
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
|
||||||
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal, 0, info.levels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(Instance& instance, CommandScheduler& scheduler, PoolManager& pool_manager,
|
Texture::Texture(Instance& instance, CommandScheduler& scheduler, PoolManager& pool_manager,
|
||||||
@ -170,19 +165,10 @@ void Texture::Free() {
|
|||||||
pool_manager.Free<Texture>(this);
|
pool_manager.Free<Texture>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout, u32 level, u32 level_count) {
|
void Texture::TransitionSubresource(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout,
|
||||||
ASSERT(level + level_count < TEXTURE_MAX_LEVELS);
|
u32 level, u32 level_count) {
|
||||||
|
|
||||||
// Ensure all miplevels in the range have the same layout
|
|
||||||
vk::ImageLayout old_layout = layouts[level];
|
|
||||||
if (old_layout != vk::ImageLayout::eUndefined) {
|
|
||||||
for (u32 i = 0; i < level_count; i++) {
|
|
||||||
ASSERT(layouts[level + i] == old_layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't do anything if the image is already in the wanted layout
|
// Don't do anything if the image is already in the wanted layout
|
||||||
if (new_layout == old_layout) {
|
if (new_layout == layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,13 +231,13 @@ void Texture::Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_l
|
|||||||
return info;
|
return info;
|
||||||
};
|
};
|
||||||
|
|
||||||
LayoutInfo source = GetLayoutInfo(old_layout);
|
LayoutInfo source = GetLayoutInfo(layout);
|
||||||
LayoutInfo dest = GetLayoutInfo(new_layout);
|
LayoutInfo dest = GetLayoutInfo(new_layout);
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier barrier = {
|
const vk::ImageMemoryBarrier barrier = {
|
||||||
.srcAccessMask = source.access,
|
.srcAccessMask = source.access,
|
||||||
.dstAccessMask = dest.access,
|
.dstAccessMask = dest.access,
|
||||||
.oldLayout = old_layout,
|
.oldLayout = layout,
|
||||||
.newLayout = new_layout,
|
.newLayout = new_layout,
|
||||||
.image = image,
|
.image = image,
|
||||||
.subresourceRange = {aspect, level, level_count, 0, 1}
|
.subresourceRange = {aspect, level, level_count, 0, 1}
|
||||||
@ -263,11 +249,11 @@ void Texture::Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_l
|
|||||||
{}, {}, barrier);
|
{}, {}, barrier);
|
||||||
|
|
||||||
// Update layouts
|
// Update layouts
|
||||||
SetLayout(new_layout, level, level_count);
|
layout = new_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::SetLayout(vk::ImageLayout new_layout, u32 level, u32 level_count) {
|
void Texture::Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout) {
|
||||||
std::fill_n(layouts.begin() + level, level_count, new_layout);
|
TransitionSubresource(command_buffer, new_layout, 0, info.levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32 level) {
|
void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32 level) {
|
||||||
@ -309,7 +295,7 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32
|
|||||||
std::memcpy(staging.GetMappedPtr(), data.data(), byte_count);
|
std::memcpy(staging.GetMappedPtr(), data.data(), byte_count);
|
||||||
staging.Commit(byte_count);
|
staging.Commit(byte_count);
|
||||||
|
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferDstOptimal, level);
|
Transition(command_buffer, vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
|
||||||
// Blit
|
// Blit
|
||||||
command_buffer.blitImage(staging.GetHandle(), vk::ImageLayout::eGeneral,
|
command_buffer.blitImage(staging.GetHandle(), vk::ImageLayout::eGeneral,
|
||||||
@ -361,7 +347,7 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32
|
|||||||
};
|
};
|
||||||
|
|
||||||
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferDstOptimal, level);
|
Transition(command_buffer, vk::ImageLayout::eTransferDstOptimal);
|
||||||
|
|
||||||
// Copy staging buffer to the texture
|
// Copy staging buffer to the texture
|
||||||
command_buffer.copyBufferToImage(staging.GetHandle(), image,
|
command_buffer.copyBufferToImage(staging.GetHandle(), image,
|
||||||
@ -373,11 +359,10 @@ void Texture::Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Texture::Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 level) {
|
void Texture::Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 level) {
|
||||||
const u64 byte_count = data.size();
|
const std::size_t byte_count = data.size();
|
||||||
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
||||||
|
|
||||||
// If the adverised format supports blitting then use GPU accelerated
|
// If the adverised format supports blitting use GPU accelerated format conversion.
|
||||||
// format conversion.
|
|
||||||
if (internal_format != advertised_format &&
|
if (internal_format != advertised_format &&
|
||||||
instance.IsFormatSupported(advertised_format, vk::FormatFeatureFlagBits::eBlitDst)) {
|
instance.IsFormatSupported(advertised_format, vk::FormatFeatureFlagBits::eBlitDst)) {
|
||||||
// Creating a new staging texture for each upload/download is expensive
|
// Creating a new staging texture for each upload/download is expensive
|
||||||
@ -407,7 +392,7 @@ void Texture::Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 lev
|
|||||||
.dstOffsets = offsets
|
.dstOffsets = offsets
|
||||||
};
|
};
|
||||||
|
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferSrcOptimal, level);
|
Transition(command_buffer, vk::ImageLayout::eTransferSrcOptimal);
|
||||||
|
|
||||||
// Blit
|
// Blit
|
||||||
command_buffer.blitImage(image, vk::ImageLayout::eTransferSrcOptimal,
|
command_buffer.blitImage(image, vk::ImageLayout::eTransferSrcOptimal,
|
||||||
@ -444,14 +429,12 @@ void Texture::Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 lev
|
|||||||
.imageExtent = {rectangle.width, rectangle.height, 1}
|
.imageExtent = {rectangle.width, rectangle.height, 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferSrcOptimal, level);
|
Transition(command_buffer, vk::ImageLayout::eTransferSrcOptimal);
|
||||||
|
|
||||||
// Copy pixel data to the staging buffer
|
// Copy pixel data to the staging buffer
|
||||||
command_buffer.copyImageToBuffer(image, vk::ImageLayout::eTransferSrcOptimal,
|
command_buffer.copyImageToBuffer(image, vk::ImageLayout::eTransferSrcOptimal,
|
||||||
staging.GetHandle(), copy_region);
|
staging.GetHandle(), copy_region);
|
||||||
|
|
||||||
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
|
||||||
|
|
||||||
// TODO: Async downloads
|
// TODO: Async downloads
|
||||||
scheduler.Submit(true);
|
scheduler.Submit(true);
|
||||||
|
|
||||||
@ -459,6 +442,8 @@ void Texture::Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 lev
|
|||||||
auto memory = staging.Map(byte_count);
|
auto memory = staging.Map(byte_count);
|
||||||
std::memcpy(data.data(), memory.data(), byte_count);
|
std::memcpy(data.data(), memory.data(), byte_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::BlitTo(TextureHandle dest, Common::Rectangle<u32> source_rect, Common::Rectangle<u32> dest_rect,
|
void Texture::BlitTo(TextureHandle dest, Common::Rectangle<u32> source_rect, Common::Rectangle<u32> dest_rect,
|
||||||
@ -514,8 +499,8 @@ void Texture::GenerateMipmaps() {
|
|||||||
|
|
||||||
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
|
||||||
for (u32 i = 1; i < info.levels; i++) {
|
for (u32 i = 1; i < info.levels; i++) {
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferSrcOptimal, i - 1);
|
TransitionSubresource(command_buffer, vk::ImageLayout::eTransferSrcOptimal, i - 1);
|
||||||
Transition(command_buffer, vk::ImageLayout::eTransferDstOptimal, i);
|
TransitionSubresource(command_buffer, vk::ImageLayout::eTransferDstOptimal, i);
|
||||||
|
|
||||||
const std::array source_offsets = {
|
const std::array source_offsets = {
|
||||||
vk::Offset3D{0, 0, 0},
|
vk::Offset3D{0, 0, 0},
|
||||||
@ -551,7 +536,7 @@ void Texture::GenerateMipmaps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare for shader reads
|
// Prepare for shader reads
|
||||||
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal, 0, info.levels);
|
Transition(command_buffer, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::CopyFrom(TextureHandle source) {
|
void Texture::CopyFrom(TextureHandle source) {
|
||||||
|
@ -33,39 +33,36 @@ public:
|
|||||||
vk::Image image, vk::Format format, const TextureInfo& info);
|
vk::Image image, vk::Format format, const TextureInfo& info);
|
||||||
|
|
||||||
~Texture() override;
|
~Texture() override;
|
||||||
|
|
||||||
void Free() override;
|
void Free() override;
|
||||||
|
|
||||||
void Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32 level = 0) override;
|
void Upload(Rect2D rectangle, u32 stride, std::span<const u8> data, u32 level = 0) override;
|
||||||
|
|
||||||
void Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 level = 0) override;
|
void Download(Rect2D rectangle, u32 stride, std::span<u8> data, u32 level = 0) override;
|
||||||
|
|
||||||
void BlitTo(TextureHandle dest, Common::Rectangle<u32> src_rectangle, Common::Rectangle<u32> dest_rect,
|
void BlitTo(TextureHandle dest, Common::Rectangle<u32> src_rectangle, Common::Rectangle<u32> dest_rect,
|
||||||
u32 src_level = 0, u32 dest_level = 0, u32 src_layer = 0, u32 dest_layer = 0) override;
|
u32 src_level = 0, u32 dest_level = 0, u32 src_layer = 0, u32 dest_layer = 0) override;
|
||||||
|
|
||||||
void CopyFrom(TextureHandle source) override;
|
void CopyFrom(TextureHandle source) override;
|
||||||
|
|
||||||
void GenerateMipmaps() override;
|
void GenerateMipmaps() override;
|
||||||
|
|
||||||
/// Overrides the layout of provided image subresource
|
// Overrides the layout of provided image subresource
|
||||||
void SetLayout(vk::ImageLayout new_layout, u32 level = 0, u32 level_count = 1);
|
void SetLayout(vk::ImageLayout new_layout, u32 level = 0, u32 level_count = 1);
|
||||||
|
|
||||||
/// Transitions part of the image to the provided layout
|
// Transitions the image to the provided layout
|
||||||
void Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout, u32 level = 0,
|
void Transition(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout);
|
||||||
u32 level_count = 1);
|
void TransitionSubresource(vk::CommandBuffer command_buffer, vk::ImageLayout new_layout,
|
||||||
|
u32 level = 0, u32 level_count = 1);
|
||||||
|
|
||||||
/// Returns the underlying vulkan image handle
|
// Returns the underlying vulkan image handle
|
||||||
vk::Image GetHandle() const {
|
vk::Image GetHandle() const {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Vulka image view
|
// Returns the Vulka image view
|
||||||
vk::ImageView GetView() const {
|
vk::ImageView GetView() const {
|
||||||
return image_view;
|
return image_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the internal format backing the texture.
|
// Returns the internal format backing the texture.
|
||||||
/// It may not match the input pixel format.
|
// It may not match the input pixel format.
|
||||||
vk::Format GetInternalFormat() const {
|
vk::Format GetInternalFormat() const {
|
||||||
return internal_format;
|
return internal_format;
|
||||||
}
|
}
|
||||||
@ -74,12 +71,12 @@ public:
|
|||||||
return aspect;
|
return aspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current image layout
|
// Returns the current image layout
|
||||||
vk::ImageLayout GetLayout(u32 level = 0) const {
|
vk::ImageLayout GetLayout(u32 level = 0) const {
|
||||||
return layouts.at(level);
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a rectangle that represents the complete area of the texture
|
// Returns a rectangle that represents the complete area of the texture
|
||||||
vk::Rect2D GetArea() const {
|
vk::Rect2D GetArea() const {
|
||||||
return {{0, 0},{info.width, info.height}};
|
return {{0, 0},{info.width, info.height}};
|
||||||
}
|
}
|
||||||
@ -99,7 +96,7 @@ private:
|
|||||||
vk::Format advertised_format = vk::Format::eUndefined;
|
vk::Format advertised_format = vk::Format::eUndefined;
|
||||||
vk::Format internal_format = vk::Format::eUndefined;
|
vk::Format internal_format = vk::Format::eUndefined;
|
||||||
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eNone;
|
vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eNone;
|
||||||
std::array<vk::ImageLayout, TEXTURE_MAX_LEVELS> layouts{vk::ImageLayout::eUndefined};
|
vk::ImageLayout layout = vk::ImageLayout::eUndefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user