OpenGL: Implement textures

This commit is contained in:
Lynix 2020-04-19 15:33:56 +02:00
parent 349e915e10
commit b4b15f826d
12 changed files with 227 additions and 298 deletions

View File

@ -10,22 +10,20 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Texture.hpp> #include <Nazara/Renderer/Texture.hpp>
#include <Nazara/OpenGLRenderer/Config.hpp> #include <Nazara/OpenGLRenderer/Config.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Image.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/ImageView.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Texture.hpp>
namespace Nz namespace Nz
{ {
class NAZARA_OPENGLRENDERER_API OpenGLTexture : public Texture class NAZARA_OPENGLRENDERER_API OpenGLTexture : public Texture
{ {
public: public:
OpenGLTexture(Vk::Device& device, const TextureInfo& params); OpenGLTexture(OpenGLDevice& device, const TextureInfo& params);
OpenGLTexture(const OpenGLTexture&) = default; OpenGLTexture(const OpenGLTexture&) = default;
OpenGLTexture(OpenGLTexture&&) noexcept = default; OpenGLTexture(OpenGLTexture&&) noexcept = default;
~OpenGLTexture(); ~OpenGLTexture() = default;
PixelFormat GetFormat() const override; PixelFormat GetFormat() const override;
inline VkImage GetImage() const;
inline VkImageView GetImageView() const;
UInt8 GetLevelCount() const override; UInt8 GetLevelCount() const override;
Vector3ui GetSize(UInt8 level = 0) const override; Vector3ui GetSize(UInt8 level = 0) const override;
ImageType GetType() const override; ImageType GetType() const override;
@ -36,12 +34,7 @@ namespace Nz
OpenGLTexture& operator=(OpenGLTexture&&) = delete; OpenGLTexture& operator=(OpenGLTexture&&) = delete;
private: private:
static void InitForFormat(PixelFormat pixelFormat, VkImageCreateInfo& createImage, VkImageViewCreateInfo& createImageView); GL::Texture m_texture;
VkImage m_image;
VmaAllocation m_allocation;
Vk::Device& m_device;
Vk::ImageView m_imageView;
TextureInfo m_params; TextureInfo m_params;
}; };
} }

View File

@ -7,15 +7,6 @@
namespace Nz namespace Nz
{ {
inline VkImage OpenGLTexture::GetImage() const
{
return m_image;
}
inline VkImageView OpenGLTexture::GetImageView() const
{
return m_imageView;
}
} }
#include <Nazara/OpenGLRenderer/DebugOff.hpp> #include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -43,6 +43,16 @@ namespace Nz::GL
KHR KHR
}; };
enum class TextureTarget
{
Cubemap,
Target2D,
Target2D_Array,
Target3D,
Max = Target3D
};
struct ContextParams struct ContextParams
{ {
ContextType type = ContextType::OpenGL_ES; ContextType type = ContextType::OpenGL_ES;
@ -63,6 +73,7 @@ namespace Nz::GL
inline Context(const OpenGLDevice* device); inline Context(const OpenGLDevice* device);
virtual ~Context(); virtual ~Context();
void BindTexture(TextureTarget target, GLuint texture) const;
virtual void EnableVerticalSync(bool enabled) = 0; virtual void EnableVerticalSync(bool enabled) = 0;
@ -75,6 +86,8 @@ namespace Nz::GL
bool Initialize(const ContextParams& params); bool Initialize(const ContextParams& params);
inline void NotifyTextureDestruction(GLuint texture) const;
virtual void SwapBuffers() = 0; virtual void SwapBuffers() = 0;
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr; #define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr;
@ -98,9 +111,15 @@ namespace Nz::GL
private: private:
void GL_APIENTRY HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const; void GL_APIENTRY HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const;
struct State
{
std::array<GLuint, UnderlyingCast(TextureTarget::Max) + 1> boundTextures;
};
std::array<ExtensionStatus, UnderlyingCast(Extension::Max) + 1> m_extensionStatus; std::array<ExtensionStatus, UnderlyingCast(Extension::Max) + 1> m_extensionStatus;
std::unordered_set<std::string> m_supportedExtensions; std::unordered_set<std::string> m_supportedExtensions;
const OpenGLDevice* m_device; const OpenGLDevice* m_device;
mutable State m_state;
}; };
} }

View File

@ -36,6 +36,15 @@ namespace Nz::GL
{ {
return m_supportedExtensions.find(extension) != m_supportedExtensions.end(); return m_supportedExtensions.find(extension) != m_supportedExtensions.end();
} }
inline void Context::NotifyTextureDestruction(GLuint texture) const
{
for (GLuint& boundTexture : m_state.boundTextures)
{
if (boundTexture == texture)
boundTexture = 0;
}
}
} }
#include <Nazara/OpenGLRenderer/DebugOff.hpp> #include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -4,40 +4,41 @@
#pragma once #pragma once
#ifndef NAZARA_OPENGLRENDERER_VKPIPELINELAYOUT_HPP #ifndef NAZARA_OPENGLRENDERER_GLTEXTURE_HPP
#define NAZARA_OPENGLRENDERER_VKPIPELINELAYOUT_HPP #define NAZARA_OPENGLRENDERER_GLTEXTURE_HPP
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp> #include <Nazara/Core/MovableValue.hpp>
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
namespace Nz namespace Nz::GL
{ {
namespace Vk class Texture
{ {
class PipelineLayout : public DeviceObject<PipelineLayout, VkPipelineLayout, VkPipelineLayoutCreateInfo, VK_OBJECT_TYPE_PIPELINE_LAYOUT> public:
{ Texture() = default;
friend DeviceObject; Texture(const Texture&) = delete;
Texture(Texture&&) noexcept = default;
inline ~Texture();
public: inline bool Create(OpenGLDevice& device);
PipelineLayout() = default; inline void Destroy();
PipelineLayout(const PipelineLayout&) = delete;
PipelineLayout(PipelineLayout&&) = default;
~PipelineLayout() = default;
using DeviceObject::Create; inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border);
bool Create(Device& device, VkDescriptorSetLayout layout, VkPipelineLayoutCreateFlags flags = 0); inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data);
bool Create(Device& device, UInt32 layoutCount, const VkDescriptorSetLayout* layouts, VkPipelineLayoutCreateFlags flags = 0); inline void TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data);
PipelineLayout& operator=(const PipelineLayout&) = delete; Texture& operator=(const Texture&) = delete;
PipelineLayout& operator=(PipelineLayout&&) = delete; Texture& operator=(Texture&&) noexcept = default;
private: private:
static inline VkResult CreateHelper(Device& device, const VkPipelineLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineLayout* handle); const Context& EnsureDeviceContext();
static inline void DestroyHelper(Device& device, VkPipelineLayout handle, const VkAllocationCallbacks* allocator);
}; MovablePtr<OpenGLDevice> m_device;
} MovableValue<GLuint> m_texture;
};
} }
#include <Nazara/OpenGLRenderer/Wrapper/PipelineLayout.inl> #include <Nazara/OpenGLRenderer/Wrapper/Texture.inl>
#endif // NAZARA_OPENGLRENDERER_VKPIPELINELAYOUT_HPP #endif

View File

@ -2,42 +2,82 @@
// This file is part of the "Nazara Engine - OpenGL Renderer" // This file is part of the "Nazara Engine - OpenGL Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/OpenGLRenderer/Wrapper/PipelineLayout.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Texture.hpp>
#include <cassert>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz namespace Nz::GL
{ {
namespace Vk inline Texture::~Texture()
{ {
inline bool PipelineLayout::Create(Device& device, VkDescriptorSetLayout layout, VkPipelineLayoutCreateFlags flags) Destroy();
}
inline bool Texture::Create(OpenGLDevice& device)
{
Destroy();
m_device = &device;
const Context& context = EnsureDeviceContext();
context.glGenTextures(1U, &m_texture.Get());
if (!m_texture)
return false; //< TODO: Handle error messages
return true;
}
inline void Texture::Destroy()
{
if (m_texture)
{ {
return Create(device, 1U, &layout, flags); const Context& context = EnsureDeviceContext();
context.glDeleteTextures(1U, &m_texture.Get());
m_device->NotifyTextureDestruction(m_texture);
m_texture = 0;
}
}
inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border)
{
return TexImage2D(level, internalFormat, width, height, border, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
}
inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data)
{
const Context& context = EnsureDeviceContext();
context.BindTexture(TextureTarget::Target2D, m_texture);
context.glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, border, format, type, data);
//< TODO: Handle errors
}
inline void Texture::TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data)
{
const Context& context = EnsureDeviceContext();
context.BindTexture(TextureTarget::Target2D, m_texture);
context.glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height, format, type, data);
//< TODO: Handle errors
}
inline const Context& Texture::EnsureDeviceContext()
{
assert(m_device);
const Context* activeContext = Context::GetCurrentContext();
if (!activeContext || activeContext->GetDevice() != m_device)
{
const Context& referenceContext = m_device->GetReferenceContext();
if (!Context::SetCurrentContext(&referenceContext))
throw std::runtime_error("failed to activate context");
return referenceContext;
} }
inline bool PipelineLayout::Create(Device& device, UInt32 layoutCount, const VkDescriptorSetLayout* layouts, VkPipelineLayoutCreateFlags flags) return *activeContext;
{
VkPipelineLayoutCreateInfo createInfo = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
nullptr,
flags,
layoutCount,
layouts,
0U,
nullptr
};
return Create(device, createInfo);
}
inline VkResult PipelineLayout::CreateHelper(Device& device, const VkPipelineLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineLayout* handle)
{
return device.vkCreatePipelineLayout(device, createInfo, allocator, handle);
}
inline void PipelineLayout::DestroyHelper(Device& device, VkPipelineLayout handle, const VkAllocationCallbacks* allocator)
{
return device.vkDestroyPipelineLayout(device, handle, allocator);
}
} }
} }

View File

@ -40,6 +40,8 @@ namespace Nz
virtual bool Update(const void* ptr) = 0; virtual bool Update(const void* ptr) = 0;
static inline unsigned int GetLevelSize(unsigned int size, unsigned int level);
Texture& operator=(const Texture&) = delete; Texture& operator=(const Texture&) = delete;
Texture& operator=(Texture&&) = delete; Texture& operator=(Texture&&) = delete;
}; };

View File

@ -7,6 +7,13 @@
namespace Nz namespace Nz
{ {
inline unsigned int Texture::GetLevelSize(unsigned int size, unsigned int level)
{
if (size == 0) // Possible dans le cas d'une image invalide
return 0;
return std::max(size >> level, 1U);
}
} }
#include <Nazara/Renderer/DebugOff.hpp> #include <Nazara/Renderer/DebugOff.hpp>

View File

@ -5,6 +5,7 @@
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp> #include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
#include <Nazara/Renderer/CommandPool.hpp> #include <Nazara/Renderer/CommandPool.hpp>
#include <Nazara/OpenGLRenderer/OpenGLShaderStage.hpp> #include <Nazara/OpenGLRenderer/OpenGLShaderStage.hpp>
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
@ -66,7 +67,7 @@ namespace Nz
std::unique_ptr<Texture> OpenGLDevice::InstantiateTexture(const TextureInfo& params) std::unique_ptr<Texture> OpenGLDevice::InstantiateTexture(const TextureInfo& params)
{ {
return {}; return std::make_unique<OpenGLTexture>(*this, params);
} }
std::unique_ptr<TextureSampler> OpenGLDevice::InstantiateTextureSampler(const TextureSamplerInfo& params) std::unique_ptr<TextureSampler> OpenGLDevice::InstantiateTextureSampler(const TextureSamplerInfo& params)

View File

@ -2,160 +2,62 @@
// This file is part of the "Nazara Engine - OpenGL Renderer" // This file is part of the "Nazara Engine - OpenGL Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#if 0
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp> #include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
#include <Nazara/Core/CallOnExit.hpp> #include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Utility/PixelFormat.hpp> #include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/CommandBuffer.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/QueueHandle.hpp>
#include <stdexcept> #include <stdexcept>
#include <vma/vk_mem_alloc.h> #include <vma/vk_mem_alloc.h>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz namespace Nz
{ {
namespace OpenGLTexture::OpenGLTexture(OpenGLDevice& device, const TextureInfo& params) :
{
inline unsigned int GetLevelSize(unsigned int size, UInt8 level)
{
if (size == 0) // Possible dans le cas d'une image invalide
return 0;
return std::max(size >> level, 1U);
}
}
OpenGLTexture::OpenGLTexture(Vk::Device& device, const TextureInfo& params) :
m_image(VK_NULL_HANDLE),
m_allocation(nullptr),
m_device(device),
m_params(params) m_params(params)
{ {
VkImageCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; if (!m_texture.Create(device))
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; throw std::runtime_error("failed to create texture object");
createInfo.mipLevels = params.mipmapLevel;
createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
createInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
VkImageViewCreateInfo createInfoView = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; GLint internalFormat;
createInfoView.subresourceRange = { switch (params.pixelFormat)
VK_IMAGE_ASPECT_COLOR_BIT, {
0, case PixelFormat_RGB8:
1, {
0, internalFormat = GL_RGB8;
1 break;
}; }
InitForFormat(params.pixelFormat, createInfo, createInfoView); case PixelFormat_RGBA8:
{
internalFormat = GL_RGBA8;
break;
}
}
switch (params.type) switch (params.type)
{ {
case ImageType_1D: case ImageType_1D:
NazaraAssert(params.width > 0, "Width must be over zero");
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_1D;
createInfo.imageType = VK_IMAGE_TYPE_1D;
createInfo.extent.width = params.width;
createInfo.extent.height = 1;
createInfo.extent.depth = 1;
createInfo.arrayLayers = 1;
break; break;
case ImageType_1D_Array: case ImageType_1D_Array:
NazaraAssert(params.width > 0, "Width must be over zero");
NazaraAssert(params.height > 0, "Height must be over zero");
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
createInfo.imageType = VK_IMAGE_TYPE_1D;
createInfo.extent.width = params.width;
createInfo.extent.height = 1;
createInfo.extent.depth = 1;
createInfo.arrayLayers = params.height;
break; break;
case ImageType_2D: case ImageType_2D:
NazaraAssert(params.width > 0, "Width must be over zero"); for (unsigned int level = 0; level < m_params.mipmapLevel; ++level)
NazaraAssert(params.height > 0, "Height must be over zero"); m_texture.TexImage2D(0, internalFormat, GetLevelSize(params.width, level), GetLevelSize(params.height, level), 0);
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.imageType = VK_IMAGE_TYPE_2D;
createInfo.extent.width = params.width;
createInfo.extent.height = params.height;
createInfo.extent.depth = 1;
createInfo.arrayLayers = 1;
break; break;
case ImageType_2D_Array: case ImageType_2D_Array:
NazaraAssert(params.width > 0, "Width must be over zero");
NazaraAssert(params.height > 0, "Height must be over zero");
NazaraAssert(params.depth > 0, "Depth must be over zero");
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
createInfo.imageType = VK_IMAGE_TYPE_2D;
createInfo.extent.width = params.width;
createInfo.extent.height = params.height;
createInfo.extent.depth = 1;
createInfo.arrayLayers = params.height;
break; break;
case ImageType_3D: case ImageType_3D:
NazaraAssert(params.width > 0, "Width must be over zero");
NazaraAssert(params.height > 0, "Height must be over zero");
NazaraAssert(params.depth > 0, "Depth must be over zero");
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_3D;
createInfo.imageType = VK_IMAGE_TYPE_3D;
createInfo.extent.width = params.width;
createInfo.extent.height = params.height;
createInfo.extent.depth = params.depth;
createInfo.arrayLayers = 1;
break; break;
case ImageType_Cubemap: case ImageType_Cubemap:
NazaraAssert(params.width > 0, "Width must be over zero");
NazaraAssert(params.height > 0, "Height must be over zero");
createInfoView.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
createInfo.imageType = VK_IMAGE_TYPE_2D;
createInfo.extent.width = params.width;
createInfo.extent.height = params.height;
createInfo.extent.depth = 1;
createInfo.arrayLayers = 6;
createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
break; break;
default: default:
break; break;
} }
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VkResult result = vmaCreateImage(m_device.GetMemoryAllocator(), &createInfo, &allocInfo, &m_image, &m_allocation, nullptr);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to allocate image: " + TranslateOpenGLError(result));
createInfoView.image = m_image;
if (!m_imageView.Create(device, createInfoView))
{
// FIXME
vmaDestroyImage(m_device.GetMemoryAllocator(), m_image, m_allocation);
throw std::runtime_error("Failed to create image view: " + TranslateOpenGLError(m_imageView.GetLastErrorCode()));
}
}
OpenGLTexture::~OpenGLTexture()
{
vmaDestroyImage(m_device.GetMemoryAllocator(), m_image, m_allocation);
} }
PixelFormat OpenGLTexture::GetFormat() const PixelFormat OpenGLTexture::GetFormat() const
@ -180,112 +82,50 @@ namespace Nz
bool OpenGLTexture::Update(const void* ptr) bool OpenGLTexture::Update(const void* ptr)
{ {
std::size_t textureSize = m_params.width * m_params.height * m_params.depth * PixelFormatInfo::GetBytesPerPixel(m_params.pixelFormat); GLint format;
GLint type;
VkBufferCreateInfo createInfo = {}; switch (m_params.pixelFormat)
createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
createInfo.size = textureSize;
createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaAllocationCreateInfo allocInfo = {};
allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
VmaAllocationInfo allocationInfo;
VkBuffer stagingBuffer;
VmaAllocation stagingAllocation;
VkResult result = vmaCreateBuffer(m_device.GetMemoryAllocator(), &createInfo, &allocInfo, &stagingBuffer, &stagingAllocation, &allocationInfo);
if (result != VK_SUCCESS)
{ {
NazaraError("Failed to allocate staging buffer: " + TranslateOpenGLError(result));
return false;
}
CallOnExit freeStaging([&] {
vmaDestroyBuffer(m_device.GetMemoryAllocator(), stagingBuffer, stagingAllocation);
});
std::memcpy(allocationInfo.pMappedData, ptr, textureSize);
Vk::AutoCommandBuffer copyCommandBuffer = m_device.AllocateCommandBuffer(QueueType::Graphics);
if (!copyCommandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT))
return false;
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyCommandBuffer->CopyBufferToImage(stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_params.width, m_params.height, m_params.depth);
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if (!copyCommandBuffer->End())
return false;
Vk::QueueHandle transferQueue = m_device.GetQueue(m_device.GetDefaultFamilyIndex(QueueType::Graphics), 0);
if (!transferQueue.Submit(copyCommandBuffer))
return false;
transferQueue.WaitIdle();
return true;
}
void OpenGLTexture::InitForFormat(PixelFormat pixelFormat, VkImageCreateInfo& createImage, VkImageViewCreateInfo& createImageView)
{
createImageView.components = {
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A
};
switch (pixelFormat)
{
case PixelFormat_L8:
{
createImage.format = VK_FORMAT_R8_SRGB;
createImageView.format = createImage.format;
createImageView.components = {
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_A
};
break;
}
case PixelFormat_LA8:
{
createImage.format = VK_FORMAT_R8G8_SRGB;
createImageView.format = createImage.format;
createImageView.components = {
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_G
};
break;
}
case PixelFormat_RGB8: case PixelFormat_RGB8:
{ {
createImage.format = VK_FORMAT_R8G8B8_SRGB; format = GL_RGB;
createImageView.format = createImage.format; type = GL_UNSIGNED_BYTE;
break; break;
} }
case PixelFormat_RGBA8: case PixelFormat_RGBA8:
{ {
createImage.format = VK_FORMAT_R8G8B8A8_SRGB; format = GL_RGBA;
createImageView.format = createImage.format; type = GL_UNSIGNED_BYTE;
break; break;
} }
}
switch (m_params.type)
{
case ImageType_1D:
break;
case ImageType_1D_Array:
break;
case ImageType_2D:
m_texture.TexSubImage2D(0, 0, 0, m_params.width, m_params.height, format, type, ptr);
break;
case ImageType_2D_Array:
break;
case ImageType_3D:
break;
case ImageType_Cubemap:
break;
default: default:
throw std::runtime_error(("Unsupported pixel format " + PixelFormatInfo::GetName(pixelFormat)).ToStdString()); break;
} }
return true;
} }
} }
#endif

View File

@ -22,6 +22,41 @@ namespace Nz::GL
m_device->NotifyContextDestruction(*this); m_device->NotifyContextDestruction(*this);
} }
void Context::BindTexture(TextureTarget target, GLuint texture) const
{
if (!SetCurrentContext(this))
throw std::runtime_error("failed to activate context");
if (m_state.boundTextures[UnderlyingCast(target)] != texture)
{
GLenum glTarget;
switch (target)
{
case TextureTarget::Cubemap:
glTarget = GL_TEXTURE_CUBE_MAP;
break;
case TextureTarget::Target2D:
glTarget = GL_TEXTURE_2D;
break;
case TextureTarget::Target2D_Array:
glTarget = GL_TEXTURE_2D_ARRAY;
break;
case TextureTarget::Target3D:
glTarget = GL_TEXTURE_3D;
break;
default:
break;
}
glBindTexture(glTarget, texture);
m_state.boundTextures[UnderlyingCast(target)] = texture;
}
}
bool Context::Initialize(const ContextParams& params) bool Context::Initialize(const ContextParams& params)
{ {
@ -31,6 +66,8 @@ namespace Nz::GL
return false; return false;
} }
m_state.boundTextures.fill(0);
const Loader& loader = GetLoader(); const Loader& loader = GetLoader();
auto LoadSymbol = [&](auto& func, const char* funcName, bool mandatory) auto LoadSymbol = [&](auto& func, const char* funcName, bool mandatory)

View File

@ -13,17 +13,6 @@
namespace Nz namespace Nz
{ {
namespace
{
inline unsigned int GetLevelSize(unsigned int size, UInt8 level)
{
if (size == 0) // Possible dans le cas d'une image invalide
return 0;
return std::max(size >> level, 1U);
}
}
VulkanTexture::VulkanTexture(Vk::Device& device, const TextureInfo& params) : VulkanTexture::VulkanTexture(Vk::Device& device, const TextureInfo& params) :
m_image(VK_NULL_HANDLE), m_image(VK_NULL_HANDLE),
m_allocation(nullptr), m_allocation(nullptr),