mirror of
https://github.com/Nexoniarz/Fry3DX.git
synced 2026-11-03 04:24:26 +00:00
Pictures in the UI read as ImGui's colours are: an sRGB picture was turned linear and showed too dark (the logo in About, the Picture panel's paint) — a UNORM view on Vulkan, a skip-decode sampler on OpenGL 4.6 and 4.0, the texture's own setting before 3.3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4cc6d9e043
commit
ffaa5e8001
6 changed files with 79 additions and 5 deletions
|
|
@ -14,8 +14,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct ImDrawList;
|
||||||
|
struct ImDrawCmd;
|
||||||
|
|
||||||
namespace keel {
|
namespace keel {
|
||||||
|
|
||||||
|
// Draw callbacks round an sRGB picture drawn in the UI, so it's read as the plain numbers ImGui's
|
||||||
|
// own colours are (read as sRGB it turns linear, and looks too dark). None when uiTexture already
|
||||||
|
// gives such a view (Vulkan).
|
||||||
|
struct UiRawRead {
|
||||||
|
void (*begin)(const ImDrawList*, const ImDrawCmd*) = nullptr;
|
||||||
|
void (*end)(const ImDrawList*, const ImDrawCmd*) = nullptr;
|
||||||
|
void* data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class Window;
|
class Window;
|
||||||
using TextureId = uint32_t;
|
using TextureId = uint32_t;
|
||||||
|
|
||||||
|
|
@ -217,6 +229,7 @@ public:
|
||||||
virtual void uploadModel(uint32_t model, const KmdlModel& kmdl) = 0;
|
virtual void uploadModel(uint32_t model, const KmdlModel& kmdl) = 0;
|
||||||
// A texture as Dear ImGui's ImTextureID, for drawing it in the UI (0 = none).
|
// A texture as Dear ImGui's ImTextureID, for drawing it in the UI (0 = none).
|
||||||
virtual uint64_t uiTexture(TextureId slot) = 0;
|
virtual uint64_t uiTexture(TextureId slot) = 0;
|
||||||
|
virtual UiRawRead uiRawRead(TextureId) { return {}; }
|
||||||
// Starts a frame; false when nothing can be drawn (minimised). Sets the drawable size.
|
// Starts a frame; false when nothing can be drawn (minimised). Sets the drawable size.
|
||||||
virtual bool beginFrame(uint32_t& width, uint32_t& height) = 0;
|
virtual bool beginFrame(uint32_t& width, uint32_t& height) = 0;
|
||||||
// Renders the packet, then ImGui's draw data, and presents.
|
// Renders the packet, then ImGui's draw data, and presents.
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ public:
|
||||||
|
|
||||||
// A loaded texture for ImGui::Image (ImTextureID); 0 if it isn't one.
|
// A loaded texture for ImGui::Image (ImTextureID); 0 if it isn't one.
|
||||||
uint64_t uiTexture(TextureId texture) { return backend_ ? backend_->uiTexture(texture) : 0; }
|
uint64_t uiTexture(TextureId texture) { return backend_ ? backend_->uiTexture(texture) : 0; }
|
||||||
|
UiRawRead uiRawRead(TextureId texture) { return backend_ ? backend_->uiRawRead(texture) : UiRawRead{}; }
|
||||||
// Pixel size of a loaded texture.
|
// Pixel size of a loaded texture.
|
||||||
glm::ivec2 textureSize(TextureId texture) const {
|
glm::ivec2 textureSize(TextureId texture) const {
|
||||||
const auto it = textureSizes_.find(texture);
|
const auto it = textureSizes_.find(texture);
|
||||||
|
|
|
||||||
|
|
@ -232,6 +232,12 @@ public:
|
||||||
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
gl::SamplerParameteri(clampSampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
gl::CreateSamplers(1, &uiRawSampler_); // (UI pictures: sRGB read as plain numbers, as ImGui's colours are)
|
||||||
|
gl::SamplerParameteri(uiRawSampler_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
gl::SamplerParameteri(uiRawSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
gl::SamplerParameteri(uiRawSampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
gl::SamplerParameteri(uiRawSampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
gl::SamplerParameteri(uiRawSampler_, 0x8A48 /* GL_TEXTURE_SRGB_DECODE_EXT */, 0x8A4A /* GL_SKIP_DECODE_EXT */);
|
||||||
gl::CreateSamplers(1, &compareSampler_);
|
gl::CreateSamplers(1, &compareSampler_);
|
||||||
gl::SamplerParameteri(compareSampler_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
gl::SamplerParameteri(compareSampler_, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
gl::SamplerParameteri(compareSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
gl::SamplerParameteri(compareSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
@ -320,7 +326,7 @@ public:
|
||||||
}
|
}
|
||||||
for (GLuint b : {textureTable_, shadowTable_, draws_, joints_, frame_, mirrorFrame_, lights_, views_, cells_, indices_, push_, empty_})
|
for (GLuint b : {textureTable_, shadowTable_, draws_, joints_, frame_, mirrorFrame_, lights_, views_, cells_, indices_, push_, empty_})
|
||||||
gl::DeleteBuffers(1, &b);
|
gl::DeleteBuffers(1, &b);
|
||||||
for (GLuint s : {repeatSampler_, clampSampler_, compareSampler_}) gl::DeleteSamplers(1, &s);
|
for (GLuint s : {repeatSampler_, clampSampler_, compareSampler_, uiRawSampler_}) gl::DeleteSamplers(1, &s);
|
||||||
for (GLuint p : {meshProgram_, skinnedProgram_, shadowMeshProgram_, shadowSkinnedProgram_, boxProgram_, tonemapProgram_, skyProgram_, hzbProgram_, ssaoProgram_, ssaoBlurProgram_, ssrProgram_, adaptProgram_, volumetricProgram_, spriteProgram_,
|
for (GLuint p : {meshProgram_, skinnedProgram_, shadowMeshProgram_, shadowSkinnedProgram_, boxProgram_, tonemapProgram_, skyProgram_, hzbProgram_, ssaoProgram_, ssaoBlurProgram_, ssrProgram_, adaptProgram_, volumetricProgram_, spriteProgram_,
|
||||||
bloomDownProgram_, bloomUpProgram_, taaProgram_})
|
bloomDownProgram_, bloomUpProgram_, taaProgram_})
|
||||||
gl::DeleteProgram(p);
|
gl::DeleteProgram(p);
|
||||||
|
|
@ -358,6 +364,7 @@ public:
|
||||||
gl::TextureSubImage2D(t.texture, GLint(level), 0, 0, GLsizei(std::max(1u, w >> level)), GLsizei(std::max(1u, h >> level)), GL_RGBA,
|
gl::TextureSubImage2D(t.texture, GLint(level), 0, 0, GLsizei(std::max(1u, w >> level)), GLsizei(std::max(1u, h >> level)), GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, mips[level].data());
|
GL_UNSIGNED_BYTE, mips[level].data());
|
||||||
}
|
}
|
||||||
|
t.srgb = srgb;
|
||||||
if (auto it = textures_.find(slot); it != textures_.end()) retiredTextures_.emplace_back(frameNumber_, it->second); // queued draws may use it
|
if (auto it = textures_.find(slot); it != textures_.end()) retiredTextures_.emplace_back(frameNumber_, it->second); // queued draws may use it
|
||||||
setHandles(slot, t, repeatSampler_, false); // like Vulkan: one repeating sampler for every texture
|
setHandles(slot, t, repeatSampler_, false); // like Vulkan: one repeating sampler for every texture
|
||||||
textures_[slot] = t;
|
textures_[slot] = t;
|
||||||
|
|
@ -385,6 +392,13 @@ public:
|
||||||
const auto it = textures_.find(slot);
|
const auto it = textures_.find(slot);
|
||||||
return it == textures_.end() ? 0 : uint64_t(it->second.texture);
|
return it == textures_.end() ? 0 : uint64_t(it->second.texture);
|
||||||
}
|
}
|
||||||
|
UiRawRead uiRawRead(TextureId slot) override {
|
||||||
|
const auto it = textures_.find(slot);
|
||||||
|
if (it == textures_.end() || !it->second.srgb) return {};
|
||||||
|
// (A sampler, not the texture's own setting: that's fixed once it has a bindless handle.)
|
||||||
|
return {[](const ImDrawList*, const ImDrawCmd* c) { gl::BindSampler(0, GLuint(uintptr_t(c->UserCallbackData))); },
|
||||||
|
[](const ImDrawList*, const ImDrawCmd*) { gl::BindSampler(0, 0); }, reinterpret_cast<void*>(uintptr_t(uiRawSampler_))};
|
||||||
|
}
|
||||||
|
|
||||||
bool beginFrame(uint32_t& width, uint32_t& height) override {
|
bool beginFrame(uint32_t& width, uint32_t& height) override {
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
|
|
@ -424,6 +438,7 @@ private:
|
||||||
struct Texture {
|
struct Texture {
|
||||||
GLuint texture = 0;
|
GLuint texture = 0;
|
||||||
GLuint64 handle = 0, shadowHandle = 0;
|
GLuint64 handle = 0, shadowHandle = 0;
|
||||||
|
bool srgb = false;
|
||||||
};
|
};
|
||||||
struct Model {
|
struct Model {
|
||||||
GLuint vertices = 0, indices = 0, skin = 0;
|
GLuint vertices = 0, indices = 0, skin = 0;
|
||||||
|
|
@ -529,7 +544,7 @@ private:
|
||||||
SDL_Window* window_ = nullptr;
|
SDL_Window* window_ = nullptr;
|
||||||
SDL_GLContext context_ = nullptr;
|
SDL_GLContext context_ = nullptr;
|
||||||
bool imgui_ = false;
|
bool imgui_ = false;
|
||||||
GLuint repeatSampler_ = 0, clampSampler_ = 0, compareSampler_ = 0;
|
GLuint repeatSampler_ = 0, clampSampler_ = 0, compareSampler_ = 0, uiRawSampler_ = 0;
|
||||||
GLuint mirrorFrame_ = 0; // the mirror's pass's frame data
|
GLuint mirrorFrame_ = 0; // the mirror's pass's frame data
|
||||||
GLuint textureTable_ = 0, shadowTable_ = 0, draws_ = 0, joints_ = 0, frame_ = 0, lights_ = 0, views_ = 0, cells_ = 0, indices_ = 0;
|
GLuint textureTable_ = 0, shadowTable_ = 0, draws_ = 0, joints_ = 0, frame_ = 0, lights_ = 0, views_ = 0, cells_ = 0, indices_ = 0;
|
||||||
GLuint push_ = 0, empty_ = 0, vao_ = 0;
|
GLuint push_ = 0, empty_ = 0, vao_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,11 @@ namespace {
|
||||||
X(void, DrawBuffer, (GLenum)) \
|
X(void, DrawBuffer, (GLenum)) \
|
||||||
X(void, DrawBuffers, (GLsizei, const GLenum*)) \
|
X(void, DrawBuffers, (GLsizei, const GLenum*)) \
|
||||||
X(void, TexBuffer, (GLenum, GLenum, GLuint)) \
|
X(void, TexBuffer, (GLenum, GLenum, GLuint)) \
|
||||||
X(void, BindFragDataLocation, (GLuint, GLuint, const GLchar*))
|
X(void, BindFragDataLocation, (GLuint, GLuint, const GLchar*)) \
|
||||||
|
X(void, GenSamplers, (GLsizei, GLuint*)) \
|
||||||
|
X(void, DeleteSamplers, (GLsizei, const GLuint*)) \
|
||||||
|
X(void, BindSampler, (GLuint, GLuint)) \
|
||||||
|
X(void, SamplerParameteri, (GLuint, GLenum, GLint))
|
||||||
|
|
||||||
namespace glx {
|
namespace glx {
|
||||||
#define KEEL_GLX_DECLARE(ret, name, params) using name##_t = ret(APIENTRY*) params; name##_t name = nullptr;
|
#define KEEL_GLX_DECLARE(ret, name, params) using name##_t = ret(APIENTRY*) params; name##_t name = nullptr;
|
||||||
|
|
@ -499,6 +503,14 @@ public:
|
||||||
ImGui::GetIO().IniFilename = nullptr;
|
ImGui::GetIO().IniFilename = nullptr;
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
imgui_ = ImGui_ImplSDL3_InitForOpenGL(window_, context_) && ImGui_ImplOpenGL3_Init(es_ ? "#version 300 es" : "#version 140");
|
imgui_ = ImGui_ImplSDL3_InitForOpenGL(window_, context_) && ImGui_ImplOpenGL3_Init(es_ ? "#version 300 es" : "#version 140");
|
||||||
|
if (glx::GenSamplers && glx::BindSampler && glx::SamplerParameteri) { // (3.3 on: UI pictures read as plain numbers, as ImGui's colours are)
|
||||||
|
glx::GenSamplers(1, &uiRawSampler_);
|
||||||
|
glx::SamplerParameteri(uiRawSampler_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glx::SamplerParameteri(uiRawSampler_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glx::SamplerParameteri(uiRawSampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glx::SamplerParameteri(uiRawSampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glx::SamplerParameteri(uiRawSampler_, 0x8A48 /* GL_TEXTURE_SRGB_DECODE_EXT */, 0x8A4A /* GL_SKIP_DECODE_EXT */);
|
||||||
|
}
|
||||||
log::info("Fallback renderer: tier {} ({})", tier_, tier_ >= 2 ? "shadows, normal maps, highlights, sky reflections, 16 lights" : "lightmaps, sun shadows, sky");
|
log::info("Fallback renderer: tier {} ({})", tier_, tier_ >= 2 ? "shadows, normal maps, highlights, sky reflections, 16 lights" : "lightmaps, sun shadows, sky");
|
||||||
return imgui_;
|
return imgui_;
|
||||||
}
|
}
|
||||||
|
|
@ -515,6 +527,7 @@ public:
|
||||||
for (GLuint t : textures_)
|
for (GLuint t : textures_)
|
||||||
if (t) glx::DeleteTextures(1, &t);
|
if (t) glx::DeleteTextures(1, &t);
|
||||||
for (Model& m : models_) releaseModel(m);
|
for (Model& m : models_) releaseModel(m);
|
||||||
|
if (uiRawSampler_) glx::DeleteSamplers(1, &uiRawSampler_);
|
||||||
releaseTargets();
|
releaseTargets();
|
||||||
for (GLuint* t : {&shadowMap_, &jointTexture_}) glx::DeleteTextures(1, t);
|
for (GLuint* t : {&shadowMap_, &jointTexture_}) glx::DeleteTextures(1, t);
|
||||||
glx::DeleteFramebuffers(1, &shadowFbo_);
|
glx::DeleteFramebuffers(1, &shadowFbo_);
|
||||||
|
|
@ -538,7 +551,8 @@ public:
|
||||||
// No block compression here (old GPUs): the renderer decodes BC7 to RGBA8 first.
|
// No block compression here (old GPUs): the renderer decodes BC7 to RGBA8 first.
|
||||||
void createTexture(TextureId slot, uint32_t w, uint32_t h, bool srgb, const std::vector<std::vector<uint8_t>>& mips,
|
void createTexture(TextureId slot, uint32_t w, uint32_t h, bool srgb, const std::vector<std::vector<uint8_t>>& mips,
|
||||||
TexFormat = TexFormat::RGBA8) override {
|
TexFormat = TexFormat::RGBA8) override {
|
||||||
if (slot >= textures_.size()) textures_.resize(slot + 1, 0);
|
if (slot >= textures_.size()) textures_.resize(slot + 1, 0), srgb_.resize(slot + 1, false);
|
||||||
|
srgb_[slot] = srgb;
|
||||||
GLuint& t = textures_[slot];
|
GLuint& t = textures_[slot];
|
||||||
if (!t) glx::GenTextures(1, &t);
|
if (!t) glx::GenTextures(1, &t);
|
||||||
glx::BindTexture(GL_TEXTURE_2D, t);
|
glx::BindTexture(GL_TEXTURE_2D, t);
|
||||||
|
|
@ -585,6 +599,22 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t uiTexture(TextureId slot) override { return slot < textures_.size() ? uint64_t(textures_[slot]) : 0; }
|
uint64_t uiTexture(TextureId slot) override { return slot < textures_.size() ? uint64_t(textures_[slot]) : 0; }
|
||||||
|
// (A sampler object where there are any; else the texture's own setting, switched for the draw and back.)
|
||||||
|
UiRawRead uiRawRead(TextureId slot) override {
|
||||||
|
if (slot >= textures_.size() || !srgb_[slot]) return {};
|
||||||
|
if (uiRawSampler_)
|
||||||
|
return {[](const ImDrawList*, const ImDrawCmd* c) { glx::BindSampler(0, GLuint(uintptr_t(c->UserCallbackData))); },
|
||||||
|
[](const ImDrawList*, const ImDrawCmd*) { glx::BindSampler(0, 0); }, reinterpret_cast<void*>(uintptr_t(uiRawSampler_))};
|
||||||
|
return {[](const ImDrawList*, const ImDrawCmd* c) {
|
||||||
|
glx::BindTexture(GL_TEXTURE_2D, GLuint(uintptr_t(c->UserCallbackData)));
|
||||||
|
glx::TexParameteri(GL_TEXTURE_2D, 0x8A48 /* GL_TEXTURE_SRGB_DECODE_EXT */, 0x8A4A /* GL_SKIP_DECODE_EXT */);
|
||||||
|
},
|
||||||
|
[](const ImDrawList*, const ImDrawCmd* c) {
|
||||||
|
glx::BindTexture(GL_TEXTURE_2D, GLuint(uintptr_t(c->UserCallbackData)));
|
||||||
|
glx::TexParameteri(GL_TEXTURE_2D, 0x8A48 /* GL_TEXTURE_SRGB_DECODE_EXT */, 0x8A49 /* GL_DECODE_EXT */);
|
||||||
|
},
|
||||||
|
reinterpret_cast<void*>(uintptr_t(textures_[slot]))};
|
||||||
|
}
|
||||||
|
|
||||||
bool beginFrame(uint32_t& width, uint32_t& height) override {
|
bool beginFrame(uint32_t& width, uint32_t& height) override {
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
|
|
@ -722,6 +752,8 @@ private:
|
||||||
bool imgui_ = false;
|
bool imgui_ = false;
|
||||||
Program mesh_, depth_, sky_, box_, tonemap_, sprite_;
|
Program mesh_, depth_, sky_, box_, tonemap_, sprite_;
|
||||||
std::vector<GLuint> textures_;
|
std::vector<GLuint> textures_;
|
||||||
|
std::vector<bool> srgb_;
|
||||||
|
GLuint uiRawSampler_ = 0;
|
||||||
std::vector<Model> models_;
|
std::vector<Model> models_;
|
||||||
GLuint frameUbo_ = 0, jointBuffer_ = 0, jointTexture_ = 0, emptyVao_ = 0;
|
GLuint frameUbo_ = 0, jointBuffer_ = 0, jointTexture_ = 0, emptyVao_ = 0;
|
||||||
GLuint shadowMap_ = 0, shadowFbo_ = 0;
|
GLuint shadowMap_ = 0, shadowFbo_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
GLenum format, GLsizei size, const void* data)) \
|
GLenum format, GLsizei size, const void* data)) \
|
||||||
X(void, CreateSamplers, (GLsizei n, GLuint* samplers)) \
|
X(void, CreateSamplers, (GLsizei n, GLuint* samplers)) \
|
||||||
X(void, DeleteSamplers, (GLsizei n, const GLuint* samplers)) \
|
X(void, DeleteSamplers, (GLsizei n, const GLuint* samplers)) \
|
||||||
|
X(void, BindSampler, (GLuint unit, GLuint sampler)) \
|
||||||
X(void, SamplerParameteri, (GLuint sampler, GLenum pname, GLint param)) \
|
X(void, SamplerParameteri, (GLuint sampler, GLenum pname, GLint param)) \
|
||||||
X(void, SamplerParameterf, (GLuint sampler, GLenum pname, GLfloat param)) \
|
X(void, SamplerParameterf, (GLuint sampler, GLenum pname, GLfloat param)) \
|
||||||
X(GLuint64, GetTextureSamplerHandleARB, (GLuint texture, GLuint sampler)) \
|
X(GLuint64, GetTextureSamplerHandleARB, (GLuint texture, GLuint sampler)) \
|
||||||
|
|
|
||||||
|
|
@ -425,6 +425,7 @@ public:
|
||||||
ici.arrayLayers = 1;
|
ici.arrayLayers = 1;
|
||||||
ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
if (srgb) ici.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; // (the UI reads it as plain numbers: uiView)
|
||||||
VmaAllocationCreateInfo aci{};
|
VmaAllocationCreateInfo aci{};
|
||||||
aci.usage = VMA_MEMORY_USAGE_AUTO;
|
aci.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
VK_CHECK(vmaCreateImage(device_.allocator(), &ici, &aci, &t.image, &t.alloc, nullptr));
|
VK_CHECK(vmaCreateImage(device_.allocator(), &ici, &aci, &t.image, &t.alloc, nullptr));
|
||||||
|
|
@ -454,6 +455,12 @@ public:
|
||||||
vci.format = format;
|
vci.format = format;
|
||||||
vci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, uint32_t(mips.size()), 0, 1};
|
vci.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, uint32_t(mips.size()), 0, 1};
|
||||||
VK_CHECK(vkCreateImageView(device_.device(), &vci, nullptr, &t.view));
|
VK_CHECK(vkCreateImageView(device_.device(), &vci, nullptr, &t.view));
|
||||||
|
// ImGui's colours are sRGB numbers drawn as they are, so the UI must read the picture without
|
||||||
|
// turning it linear first (else it shows too dark): the same image, seen as UNORM.
|
||||||
|
if (srgb) {
|
||||||
|
vci.format = fmt == TexFormat::BC7 ? VK_FORMAT_BC7_UNORM_BLOCK : VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
VK_CHECK(vkCreateImageView(device_.device(), &vci, nullptr, &t.uiView));
|
||||||
|
}
|
||||||
if (textures_.size() <= slot) textures_.resize(slot + 1);
|
if (textures_.size() <= slot) textures_.resize(slot + 1);
|
||||||
// Replaced (hot reload): frames in flight may still sample the old one.
|
// Replaced (hot reload): frames in flight may still sample the old one.
|
||||||
if (textures_[slot].image) retiredTextures_.emplace_back(frameNumber_, textures_[slot]);
|
if (textures_[slot].image) retiredTextures_.emplace_back(frameNumber_, textures_[slot]);
|
||||||
|
|
@ -484,7 +491,10 @@ public:
|
||||||
uiTextures_.erase(it), it = uiTextures_.end();
|
uiTextures_.erase(it), it = uiTextures_.end();
|
||||||
}
|
}
|
||||||
if (it == uiTextures_.end())
|
if (it == uiTextures_.end())
|
||||||
it = uiTextures_.emplace(slot, UiTexture{uint64_t(ImGui_ImplVulkan_AddTexture(sampler_, textures_[slot].view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)), textures_[slot].view}).first;
|
it = uiTextures_.emplace(slot, UiTexture{uint64_t(ImGui_ImplVulkan_AddTexture(sampler_, textures_[slot].uiView ? textures_[slot].uiView : textures_[slot].view,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)),
|
||||||
|
textures_[slot].view})
|
||||||
|
.first;
|
||||||
return it->second.set;
|
return it->second.set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -535,6 +545,7 @@ private:
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
VmaAllocation alloc = VK_NULL_HANDLE;
|
VmaAllocation alloc = VK_NULL_HANDLE;
|
||||||
VkImageView view = VK_NULL_HANDLE;
|
VkImageView view = VK_NULL_HANDLE;
|
||||||
|
VkImageView uiView = VK_NULL_HANDLE; // (an sRGB picture seen as UNORM, for the UI)
|
||||||
};
|
};
|
||||||
// A ray-tracing shape (bottom-level acceleration structure): one per submesh, by first index.
|
// A ray-tracing shape (bottom-level acceleration structure): one per submesh, by first index.
|
||||||
struct Blas {
|
struct Blas {
|
||||||
|
|
@ -549,6 +560,7 @@ private:
|
||||||
|
|
||||||
void destroyTexture(Texture& t) {
|
void destroyTexture(Texture& t) {
|
||||||
if (t.view) vkDestroyImageView(device_.device(), t.view, nullptr);
|
if (t.view) vkDestroyImageView(device_.device(), t.view, nullptr);
|
||||||
|
if (t.uiView) vkDestroyImageView(device_.device(), t.uiView, nullptr);
|
||||||
if (t.image) vmaDestroyImage(device_.allocator(), t.image, t.alloc);
|
if (t.image) vmaDestroyImage(device_.allocator(), t.image, t.alloc);
|
||||||
t = {};
|
t = {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue