Fix OpenGL sampler and copy semantics
This commit is contained in:
@@ -35,7 +35,9 @@ struct OpenGLSamplerDesc {
|
|||||||
SamplerWrapMode wrapR = SamplerWrapMode::Repeat;
|
SamplerWrapMode wrapR = SamplerWrapMode::Repeat;
|
||||||
SamplerCompareMode compareMode = SamplerCompareMode::None;
|
SamplerCompareMode compareMode = SamplerCompareMode::None;
|
||||||
int compareFunc = 0;
|
int compareFunc = 0;
|
||||||
|
float mipLodBias = 0.0f;
|
||||||
float maxAnisotropy = 1.0f;
|
float maxAnisotropy = 1.0f;
|
||||||
|
float borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
float minLod = -1000.0f;
|
float minLod = -1000.0f;
|
||||||
float maxLod = 1000.0f;
|
float maxLod = 1000.0f;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLRenderPass.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLEnums.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLEnums.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
@@ -830,10 +831,17 @@ void OpenGLCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src)
|
|||||||
|
|
||||||
GLuint dstTex = dstView->GetTexture();
|
GLuint dstTex = dstView->GetTexture();
|
||||||
GLuint srcTex = srcView->GetTexture();
|
GLuint srcTex = srcView->GetTexture();
|
||||||
if (dstTex && srcTex) {
|
const OpenGLTexture* dstTexture = dstView->GetTextureResource();
|
||||||
glCopyImageSubData(srcTex, GL_TEXTURE_2D, 0, 0, 0, 0,
|
const OpenGLTexture* srcTexture = srcView->GetTextureResource();
|
||||||
dstTex, GL_TEXTURE_2D, 0, 0, 0, 0,
|
if (dstTex && srcTex && dstTexture != nullptr && srcTexture != nullptr) {
|
||||||
256, 256, 1);
|
const GLuint srcTarget = ToOpenGL(srcTexture->GetOpenGLType());
|
||||||
|
const GLuint dstTarget = ToOpenGL(dstTexture->GetOpenGLType());
|
||||||
|
const GLsizei copyWidth = static_cast<GLsizei>(std::min(srcTexture->GetWidth(), dstTexture->GetWidth()));
|
||||||
|
const GLsizei copyHeight = static_cast<GLsizei>(std::min(srcTexture->GetHeight(), dstTexture->GetHeight()));
|
||||||
|
const GLsizei copyDepth = static_cast<GLsizei>(std::max<uint32_t>(1u, std::min(srcTexture->GetDepth(), dstTexture->GetDepth())));
|
||||||
|
glCopyImageSubData(srcTex, srcTarget, 0, 0, 0, 0,
|
||||||
|
dstTex, dstTarget, 0, 0, 0, 0,
|
||||||
|
copyWidth, copyHeight, copyDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "XCEngine/RHI/OpenGL/OpenGLTexture.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLTexture.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLShader.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLPipelineState.h"
|
||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLEnums.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLFence.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLFence.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
|
||||||
@@ -121,6 +122,75 @@ FramebufferAttachmentType ResolveDepthAttachmentType(Format format) {
|
|||||||
: FramebufferAttachmentType::Depth;
|
: FramebufferAttachmentType::Depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SamplerWrapMode ToOpenGLSamplerWrapMode(TextureAddressMode mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case TextureAddressMode::Wrap:
|
||||||
|
return SamplerWrapMode::Repeat;
|
||||||
|
case TextureAddressMode::Mirror:
|
||||||
|
return SamplerWrapMode::MirroredRepeat;
|
||||||
|
case TextureAddressMode::Clamp:
|
||||||
|
return SamplerWrapMode::ClampToEdge;
|
||||||
|
case TextureAddressMode::Border:
|
||||||
|
return SamplerWrapMode::ClampToBorder;
|
||||||
|
case TextureAddressMode::MirrorOnce:
|
||||||
|
return SamplerWrapMode::ClampToEdge;
|
||||||
|
default:
|
||||||
|
return SamplerWrapMode::Repeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLSamplerDesc ToOpenGLSamplerDesc(const SamplerDesc& desc) {
|
||||||
|
OpenGLSamplerDesc glDesc = {};
|
||||||
|
const FilterMode filter = static_cast<FilterMode>(desc.filter);
|
||||||
|
switch (filter) {
|
||||||
|
case FilterMode::Point:
|
||||||
|
glDesc.minFilter = SamplerFilter::Nearest;
|
||||||
|
glDesc.magFilter = SamplerFilter::Nearest;
|
||||||
|
break;
|
||||||
|
case FilterMode::Linear:
|
||||||
|
glDesc.minFilter = SamplerFilter::Linear;
|
||||||
|
glDesc.magFilter = SamplerFilter::Linear;
|
||||||
|
break;
|
||||||
|
case FilterMode::Anisotropic:
|
||||||
|
glDesc.minFilter = SamplerFilter::LinearMipmapLinear;
|
||||||
|
glDesc.magFilter = SamplerFilter::Linear;
|
||||||
|
glDesc.maxAnisotropy = desc.maxAnisotropy > 0 ? static_cast<float>(desc.maxAnisotropy) : 1.0f;
|
||||||
|
break;
|
||||||
|
case FilterMode::ComparisonPoint:
|
||||||
|
glDesc.minFilter = SamplerFilter::Nearest;
|
||||||
|
glDesc.magFilter = SamplerFilter::Nearest;
|
||||||
|
glDesc.compareMode = SamplerCompareMode::CompareToRef;
|
||||||
|
break;
|
||||||
|
case FilterMode::ComparisonLinear:
|
||||||
|
glDesc.minFilter = SamplerFilter::Linear;
|
||||||
|
glDesc.magFilter = SamplerFilter::Linear;
|
||||||
|
glDesc.compareMode = SamplerCompareMode::CompareToRef;
|
||||||
|
break;
|
||||||
|
case FilterMode::ComparisonAnisotropic:
|
||||||
|
glDesc.minFilter = SamplerFilter::LinearMipmapLinear;
|
||||||
|
glDesc.magFilter = SamplerFilter::Linear;
|
||||||
|
glDesc.compareMode = SamplerCompareMode::CompareToRef;
|
||||||
|
glDesc.maxAnisotropy = desc.maxAnisotropy > 0 ? static_cast<float>(desc.maxAnisotropy) : 1.0f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDesc.wrapS = ToOpenGLSamplerWrapMode(static_cast<TextureAddressMode>(desc.addressU));
|
||||||
|
glDesc.wrapT = ToOpenGLSamplerWrapMode(static_cast<TextureAddressMode>(desc.addressV));
|
||||||
|
glDesc.wrapR = ToOpenGLSamplerWrapMode(static_cast<TextureAddressMode>(desc.addressW));
|
||||||
|
glDesc.compareFunc = static_cast<int>(ToOpenGL(static_cast<ComparisonFunc>(desc.comparisonFunc)));
|
||||||
|
glDesc.mipLodBias = desc.mipLodBias;
|
||||||
|
glDesc.maxAnisotropy = glDesc.maxAnisotropy < 1.0f ? 1.0f : glDesc.maxAnisotropy;
|
||||||
|
glDesc.borderColor[0] = desc.borderColorR;
|
||||||
|
glDesc.borderColor[1] = desc.borderColorG;
|
||||||
|
glDesc.borderColor[2] = desc.borderColorB;
|
||||||
|
glDesc.borderColor[3] = desc.borderColorA;
|
||||||
|
glDesc.minLod = desc.minLod;
|
||||||
|
glDesc.maxLod = desc.maxLod;
|
||||||
|
return glDesc;
|
||||||
|
}
|
||||||
|
|
||||||
HWND CreateHiddenOpenGLWindow() {
|
HWND CreateHiddenOpenGLWindow() {
|
||||||
WNDCLASSEXW wc = {};
|
WNDCLASSEXW wc = {};
|
||||||
wc.cbSize = sizeof(WNDCLASSEXW);
|
wc.cbSize = sizeof(WNDCLASSEXW);
|
||||||
@@ -684,8 +754,11 @@ RHIFence* OpenGLDevice::CreateFence(const FenceDesc& desc) {
|
|||||||
|
|
||||||
RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
|
RHISampler* OpenGLDevice::CreateSampler(const SamplerDesc& desc) {
|
||||||
auto* sampler = new OpenGLSampler();
|
auto* sampler = new OpenGLSampler();
|
||||||
OpenGLSamplerDesc samplerDesc = {};
|
const OpenGLSamplerDesc samplerDesc = ToOpenGLSamplerDesc(desc);
|
||||||
sampler->Initialize(samplerDesc);
|
if (!sampler->Initialize(samplerDesc)) {
|
||||||
|
delete sampler;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return sampler;
|
return sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,16 @@ bool OpenGLSampler::Initialize(const OpenGLSamplerDesc& desc) {
|
|||||||
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, ToOpenGL(desc.wrapS));
|
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, ToOpenGL(desc.wrapS));
|
||||||
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, ToOpenGL(desc.wrapT));
|
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, ToOpenGL(desc.wrapT));
|
||||||
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, ToOpenGL(desc.wrapR));
|
glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, ToOpenGL(desc.wrapR));
|
||||||
|
glSamplerParameterf(m_sampler, GL_TEXTURE_LOD_BIAS, desc.mipLodBias);
|
||||||
glSamplerParameterf(m_sampler, GL_TEXTURE_MIN_LOD, desc.minLod);
|
glSamplerParameterf(m_sampler, GL_TEXTURE_MIN_LOD, desc.minLod);
|
||||||
glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_LOD, desc.maxLod);
|
glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_LOD, desc.maxLod);
|
||||||
glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.maxAnisotropy);
|
glSamplerParameterf(m_sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.maxAnisotropy);
|
||||||
|
glSamplerParameteri(
|
||||||
|
m_sampler,
|
||||||
|
GL_TEXTURE_COMPARE_MODE,
|
||||||
|
desc.compareMode == SamplerCompareMode::CompareToRef ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE);
|
||||||
|
glSamplerParameteri(m_sampler, GL_TEXTURE_COMPARE_FUNC, desc.compareFunc);
|
||||||
|
glSamplerParameterfv(m_sampler, GL_TEXTURE_BORDER_COLOR, desc.borderColor);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDevice.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace XCEngine::RHI;
|
using namespace XCEngine::RHI;
|
||||||
|
|
||||||
@@ -538,6 +539,74 @@ TEST_P(RHITestFixture, CommandList_CopyResource_WithRealResources) {
|
|||||||
delete dstTexture;
|
delete dstTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, CommandList_CopyResource_UsesActualTextureDimensionsOnOpenGL) {
|
||||||
|
if (GetBackendType() != RHIType::OpenGL) {
|
||||||
|
GTEST_SKIP() << "OpenGL-specific copy verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 64;
|
||||||
|
constexpr uint32_t kHeight = 32;
|
||||||
|
|
||||||
|
std::vector<uint8_t> srcPixels(kWidth * kHeight * 4);
|
||||||
|
for (uint32_t y = 0; y < kHeight; ++y) {
|
||||||
|
for (uint32_t x = 0; x < kWidth; ++x) {
|
||||||
|
const size_t index = static_cast<size_t>((y * kWidth + x) * 4);
|
||||||
|
srcPixels[index + 0] = static_cast<uint8_t>(x * 3);
|
||||||
|
srcPixels[index + 1] = static_cast<uint8_t>(y * 5);
|
||||||
|
srcPixels[index + 2] = static_cast<uint8_t>((x + y) * 7);
|
||||||
|
srcPixels[index + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureDesc texDesc = {};
|
||||||
|
texDesc.width = kWidth;
|
||||||
|
texDesc.height = kHeight;
|
||||||
|
texDesc.depth = 1;
|
||||||
|
texDesc.mipLevels = 1;
|
||||||
|
texDesc.arraySize = 1;
|
||||||
|
texDesc.format = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||||
|
texDesc.textureType = static_cast<uint32_t>(TextureType::Texture2D);
|
||||||
|
texDesc.sampleCount = 1;
|
||||||
|
texDesc.sampleQuality = 0;
|
||||||
|
|
||||||
|
RHITexture* srcTexture = GetDevice()->CreateTexture(texDesc, srcPixels.data(), srcPixels.size(), kWidth * 4);
|
||||||
|
ASSERT_NE(srcTexture, nullptr);
|
||||||
|
RHITexture* dstTexture = GetDevice()->CreateTexture(texDesc);
|
||||||
|
ASSERT_NE(dstTexture, nullptr);
|
||||||
|
|
||||||
|
RHIResourceView* srcView = GetDevice()->CreateShaderResourceView(srcTexture, {});
|
||||||
|
RHIResourceView* dstView = GetDevice()->CreateShaderResourceView(dstTexture, {});
|
||||||
|
ASSERT_NE(srcView, nullptr);
|
||||||
|
ASSERT_NE(dstView, nullptr);
|
||||||
|
|
||||||
|
CommandListDesc cmdDesc = {};
|
||||||
|
cmdDesc.commandListType = static_cast<uint32_t>(CommandQueueType::Direct);
|
||||||
|
RHICommandList* cmdList = GetDevice()->CreateCommandList(cmdDesc);
|
||||||
|
ASSERT_NE(cmdList, nullptr);
|
||||||
|
|
||||||
|
cmdList->Reset();
|
||||||
|
cmdList->CopyResource(dstView, srcView);
|
||||||
|
glFinish();
|
||||||
|
cmdList->Close();
|
||||||
|
|
||||||
|
std::vector<uint8_t> dstPixels(kWidth * kHeight * 4, 0);
|
||||||
|
const GLuint dstTextureId = static_cast<OpenGLResourceView*>(dstView)->GetTexture();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, dstTextureId);
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, dstPixels.data());
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
EXPECT_EQ(dstPixels, srcPixels);
|
||||||
|
|
||||||
|
cmdList->Shutdown();
|
||||||
|
delete cmdList;
|
||||||
|
delete srcView;
|
||||||
|
delete dstView;
|
||||||
|
srcTexture->Shutdown();
|
||||||
|
delete srcTexture;
|
||||||
|
dstTexture->Shutdown();
|
||||||
|
delete dstTexture;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(RHITestFixture, CommandList_BeginEndRenderPass_Basic) {
|
TEST_P(RHITestFixture, CommandList_BeginEndRenderPass_Basic) {
|
||||||
AttachmentDesc colorDesc = {};
|
AttachmentDesc colorDesc = {};
|
||||||
colorDesc.format = Format::R8G8B8A8_UNorm;
|
colorDesc.format = Format::R8G8B8A8_UNorm;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "fixtures/RHITestFixture.h"
|
#include "fixtures/RHITestFixture.h"
|
||||||
#include "XCEngine/RHI/RHISampler.h"
|
#include "XCEngine/RHI/RHISampler.h"
|
||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLSampler.h"
|
||||||
|
#include <glad/glad.h>
|
||||||
|
|
||||||
using namespace XCEngine::RHI;
|
using namespace XCEngine::RHI;
|
||||||
|
|
||||||
@@ -75,3 +77,51 @@ TEST_P(RHITestFixture, Sampler_GetNativeHandle) {
|
|||||||
sampler->Shutdown();
|
sampler->Shutdown();
|
||||||
delete sampler;
|
delete sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, Sampler_OpenGLHonorsSamplerDesc) {
|
||||||
|
if (GetBackendType() != RHIType::OpenGL) {
|
||||||
|
GTEST_SKIP() << "OpenGL-specific sampler parameter verification";
|
||||||
|
}
|
||||||
|
|
||||||
|
SamplerDesc desc = {};
|
||||||
|
desc.filter = static_cast<uint32_t>(FilterMode::ComparisonAnisotropic);
|
||||||
|
desc.addressU = static_cast<uint32_t>(TextureAddressMode::Clamp);
|
||||||
|
desc.addressV = static_cast<uint32_t>(TextureAddressMode::Mirror);
|
||||||
|
desc.addressW = static_cast<uint32_t>(TextureAddressMode::Border);
|
||||||
|
desc.maxAnisotropy = 8;
|
||||||
|
desc.comparisonFunc = static_cast<uint32_t>(ComparisonFunc::GreaterEqual);
|
||||||
|
desc.minLod = 1.0f;
|
||||||
|
desc.maxLod = 4.0f;
|
||||||
|
|
||||||
|
RHISampler* sampler = GetDevice()->CreateSampler(desc);
|
||||||
|
ASSERT_NE(sampler, nullptr);
|
||||||
|
|
||||||
|
const GLuint samplerId = static_cast<OpenGLSampler*>(sampler)->GetID();
|
||||||
|
|
||||||
|
GLint value = 0;
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_WRAP_S, &value);
|
||||||
|
EXPECT_EQ(value, GL_CLAMP_TO_EDGE);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_WRAP_T, &value);
|
||||||
|
EXPECT_EQ(value, GL_MIRRORED_REPEAT);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_WRAP_R, &value);
|
||||||
|
EXPECT_EQ(value, GL_CLAMP_TO_BORDER);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_MIN_FILTER, &value);
|
||||||
|
EXPECT_EQ(value, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_MAG_FILTER, &value);
|
||||||
|
EXPECT_EQ(value, GL_LINEAR);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_COMPARE_MODE, &value);
|
||||||
|
EXPECT_EQ(value, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
|
glGetSamplerParameteriv(samplerId, GL_TEXTURE_COMPARE_FUNC, &value);
|
||||||
|
EXPECT_EQ(value, GL_GEQUAL);
|
||||||
|
|
||||||
|
GLfloat floatValue = 0.0f;
|
||||||
|
glGetSamplerParameterfv(samplerId, GL_TEXTURE_MAX_ANISOTROPY, &floatValue);
|
||||||
|
EXPECT_GE(floatValue, 8.0f);
|
||||||
|
glGetSamplerParameterfv(samplerId, GL_TEXTURE_MIN_LOD, &floatValue);
|
||||||
|
EXPECT_FLOAT_EQ(floatValue, 1.0f);
|
||||||
|
glGetSamplerParameterfv(samplerId, GL_TEXTURE_MAX_LOD, &floatValue);
|
||||||
|
EXPECT_FLOAT_EQ(floatValue, 4.0f);
|
||||||
|
|
||||||
|
sampler->Shutdown();
|
||||||
|
delete sampler;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user