Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the PSP's equal-size mips "3D texturing" #15727

Merged
merged 16 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Common/GPU/D3D11/thin3d_d3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
caps_.framebufferCopySupported = true;
caps_.framebufferDepthBlitSupported = false;
caps_.framebufferDepthCopySupported = true;
caps_.texture3DSupported = true;

D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/D3D9/D3D9StateCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ void DirectXState::Restore() {
texMaxMipLevel.restore(); count++;
texAddressU.restore(); count++;
texAddressV.restore(); count++;
texAddressW.restore(); count++;
}

} // namespace DX9
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/D3D9/D3D9StateCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ class DirectXState {
DxSampler0State1<D3DSAMP_MAXMIPLEVEL, 0> texMaxMipLevel;
DxSampler0State1<D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP> texAddressU;
DxSampler0State1<D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP> texAddressV;
DxSampler0State1<D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP> texAddressW;
};

#undef STATE1
Expand Down
2 changes: 2 additions & 0 deletions Common/GPU/D3D9/thin3d_d3d9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,8 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
caps_.framebufferCopySupported = false;
caps_.framebufferDepthBlitSupported = true;
caps_.framebufferDepthCopySupported = false;
caps_.texture3DSupported = true;

if (d3d) {
D3DDISPLAYMODE displayMode;
d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/OpenGL/GLFeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ void CheckGLExtensions() {
gl_extensions.EXT_shader_framebuffer_fetch = g_set_gl_extensions.count("GL_EXT_shader_framebuffer_fetch") != 0;
gl_extensions.ARM_shader_framebuffer_fetch = g_set_gl_extensions.count("GL_ARM_shader_framebuffer_fetch") != 0;
gl_extensions.OES_texture_float = g_set_gl_extensions.count("GL_OES_texture_float") != 0;
gl_extensions.OES_texture_3D = g_set_gl_extensions.count("GL_OES_texture_3D") != 0;
gl_extensions.EXT_buffer_storage = g_set_gl_extensions.count("GL_EXT_buffer_storage") != 0;
gl_extensions.EXT_clip_cull_distance = g_set_gl_extensions.count("GL_EXT_clip_cull_distance") != 0;
gl_extensions.APPLE_clip_distance = g_set_gl_extensions.count("GL_APPLE_clip_distance") != 0;
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/OpenGL/GLFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct GLExtensions {
bool OES_vertex_array_object;
bool OES_copy_image;
bool OES_texture_float;
bool OES_texture_3D;

// ARB
bool ARB_framebuffer_object;
Expand Down
34 changes: 24 additions & 10 deletions Common/GPU/OpenGL/GLQueueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,17 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
GLenum internalFormat, format, type;
int alignment;
Thin3DFormatToFormatAndType(step.texture_image.format, internalFormat, format, type, alignment);
glTexImage2D(tex->target, step.texture_image.level, internalFormat, step.texture_image.width, step.texture_image.height, 0, format, type, step.texture_image.data);
if (step.texture_image.depth == 1) {
glTexImage2D(tex->target,
step.texture_image.level, internalFormat,
step.texture_image.width, step.texture_image.height, 0,
format, type, step.texture_image.data);
} else {
glTexImage3D(tex->target,
step.texture_image.level, internalFormat,
step.texture_image.width, step.texture_image.height, step.texture_image.depth, 0,
format, type, step.texture_image.data);
}
allocatedTextures = true;
if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
FreeAlignedMemory(step.texture_image.data);
Expand All @@ -364,6 +374,9 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, tex->wrapT);
glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, tex->magFilter);
glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, tex->minFilter);
if (step.texture_image.depth > 1) {
glTexParameteri(tex->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
CHECK_GL_ERROR_IF_DEBUG();
break;
}
Expand All @@ -375,7 +388,7 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
glBindTexture(tex->target, tex->texture);
boundTexture = tex->texture;
}
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
if ((!gl_extensions.IsGLES || gl_extensions.GLES3) && step.texture_finalize.loadedLevels > 1) {
glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.loadedLevels - 1);
}
tex->maxLod = (float)step.texture_finalize.loadedLevels - 1;
Expand Down Expand Up @@ -1139,28 +1152,28 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
CHECK_GL_ERROR_IF_DEBUG();
if (tex->canWrap) {
if (tex->wrapS != c.textureSampler.wrapS) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
tex->wrapS = c.textureSampler.wrapS;
}
if (tex->wrapT != c.textureSampler.wrapT) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
tex->wrapT = c.textureSampler.wrapT;
}
}
CHECK_GL_ERROR_IF_DEBUG();
if (tex->magFilter != c.textureSampler.magFilter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
tex->magFilter = c.textureSampler.magFilter;
}
CHECK_GL_ERROR_IF_DEBUG();
if (tex->minFilter != c.textureSampler.minFilter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
tex->minFilter = c.textureSampler.minFilter;
}
CHECK_GL_ERROR_IF_DEBUG();
if (tex->anisotropy != c.textureSampler.anisotropy) {
if (c.textureSampler.anisotropy != 0.0f) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
glTexParameterf(tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
}
tex->anisotropy = c.textureSampler.anisotropy;
}
Expand All @@ -1180,16 +1193,16 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
}
#ifndef USING_GLES2
if (tex->lodBias != c.textureLod.lodBias && !gl_extensions.IsGLES) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
glTexParameterf(tex->target, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
tex->lodBias = c.textureLod.lodBias;
}
#endif
if (tex->minLod != c.textureLod.minLod) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
glTexParameterf(tex->target, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
tex->minLod = c.textureLod.minLod;
}
if (tex->maxLod != c.textureLod.maxLod) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
glTexParameterf(tex->target, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
tex->maxLod = c.textureLod.maxLod;
}
break;
Expand All @@ -1200,6 +1213,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
// TODO: Need bind?
if (!c.texture_subimage.data)
Crash();
_assert_(tex->target == GL_TEXTURE_2D);
// For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
GLuint internalFormat, format, type;
int alignment;
Expand Down
5 changes: 3 additions & 2 deletions Common/GPU/OpenGL/GLQueueRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,9 @@ struct GLRInitStep {
GLRTexture *texture;
Draw::DataFormat format;
int level;
int width;
int height;
uint16_t width;
uint16_t height;
uint16_t depth;
GLRAllocType allocType;
bool linearFilter;
uint8_t *data; // owned, delete[]-d
Expand Down
3 changes: 2 additions & 1 deletion Common/GPU/OpenGL/GLRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ static bool OnRenderThread() {
}
#endif

GLRTexture::GLRTexture(int width, int height, int numMips) {
GLRTexture::GLRTexture(int width, int height, int depth, int numMips) {
if (gl_extensions.OES_texture_npot) {
canWrap = true;
} else {
canWrap = isPowerOf2(width) && isPowerOf2(height);
}
w = width;
h = height;
depth = depth;
this->numMips = numMips;
}

Expand Down
12 changes: 7 additions & 5 deletions Common/GPU/OpenGL/GLRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ constexpr int MAX_GL_TEXTURE_SLOTS = 8;

class GLRTexture {
public:
GLRTexture(int width, int height, int numMips);
GLRTexture(int width, int height, int depth, int numMips);
~GLRTexture();

GLuint texture = 0;
uint16_t w;
uint16_t h;
uint16_t d;

// We don't trust OpenGL defaults - setting wildly off values ensures that we'll end up overwriting these parameters.
GLenum target = 0xFFFF;
Expand All @@ -49,7 +50,7 @@ class GLRTexture {
class GLRFramebuffer {
public:
GLRFramebuffer(int _width, int _height, bool z_stencil)
: color_texture(_width, _height, 1), z_stencil_texture(_width, _height, 1),
: color_texture(_width, _height, 1, 1), z_stencil_texture(_width, _height, 1, 1),
width(_width), height(_height), z_stencil_(z_stencil) {
}

Expand Down Expand Up @@ -384,9 +385,9 @@ class GLRenderManager {
// Creation commands. These were not needed in Vulkan since there we can do that on the main thread.
// We pass in width/height here even though it's not strictly needed until we support glTextureStorage
// and then we'll also need formats and stuff.
GLRTexture *CreateTexture(GLenum target, int width, int height, int numMips) {
GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) {
GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE };
step.create_texture.texture = new GLRTexture(width, height, numMips);
step.create_texture.texture = new GLRTexture(width, height, depth, numMips);
step.create_texture.texture->target = target;
initSteps_.push_back(step);
return step.create_texture.texture;
Expand Down Expand Up @@ -537,14 +538,15 @@ class GLRenderManager {
}

// Takes ownership over the data pointer and delete[]-s it.
void TextureImage(GLRTexture *texture, int level, int width, int height, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) {
void TextureImage(GLRTexture *texture, int level, int width, int height, int depth, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) {
GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE };
step.texture_image.texture = texture;
step.texture_image.data = data;
step.texture_image.format = format;
step.texture_image.level = level;
step.texture_image.width = width;
step.texture_image.height = height;
step.texture_image.depth = depth;
step.texture_image.allocType = allocType;
step.texture_image.linearFilter = linearFilter;
initSteps_.push_back(step);
Expand Down
9 changes: 7 additions & 2 deletions Common/GPU/OpenGL/thin3d_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,10 @@ OpenGLContext::OpenGLContext() {
} else {
caps_.preferredDepthBufferFormat = DataFormat::D16;
}
caps_.texture3DSupported = gl_extensions.OES_texture_3D;
} else {
caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
caps_.texture3DSupported = true;
}
caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object;
caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
Expand Down Expand Up @@ -636,6 +638,7 @@ OpenGLContext::OpenGLContext() {
shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
shaderLanguageDesc_.fragColor0 = "fragColor0";
shaderLanguageDesc_.texture = "texture";
shaderLanguageDesc_.texture3D = "texture";
shaderLanguageDesc_.glslES30 = true;
shaderLanguageDesc_.bitwiseOps = true;
shaderLanguageDesc_.texelFetch = "texelFetch";
Expand All @@ -659,6 +662,7 @@ OpenGLContext::OpenGLContext() {
shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
shaderLanguageDesc_.fragColor0 = "fragColor0";
shaderLanguageDesc_.texture = "texture";
shaderLanguageDesc_.texture3D = "texture";
shaderLanguageDesc_.glslES30 = true;
shaderLanguageDesc_.bitwiseOps = true;
shaderLanguageDesc_.texelFetch = "texelFetch";
Expand All @@ -669,6 +673,7 @@ OpenGLContext::OpenGLContext() {
shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
shaderLanguageDesc_.fragColor0 = "fragColor0";
shaderLanguageDesc_.texture = "texture";
shaderLanguageDesc_.texture3D = "texture";
shaderLanguageDesc_.bitwiseOps = true;
shaderLanguageDesc_.texelFetch = "texelFetch";
shaderLanguageDesc_.varying_vs = "out";
Expand Down Expand Up @@ -792,7 +797,7 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) :
format_ = desc.format;
type_ = desc.type;
GLenum target = TypeToTarget(desc.type);
tex_ = render->CreateTexture(target, desc.width, desc.height, desc.mipLevels);
tex_ = render->CreateTexture(target, desc.width, desc.height, 1, desc.mipLevels);

mipLevels_ = desc.mipLevels;
if (desc.initData.empty())
Expand Down Expand Up @@ -877,7 +882,7 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
}
}

render_->TextureImage(tex_, level, width, height, format_, texData);
render_->TextureImage(tex_, level, width, height, depth, format_, texData);
}

#ifdef DEBUG_READ_PIXELS
Expand Down
4 changes: 4 additions & 0 deletions Common/GPU/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
fragColor0 = "gl_FragColor";
fragColor1 = "fragColor1";
texture = "texture2D";
texture3D = "texture3D";
texelFetch = nullptr;
bitwiseOps = false;
lastFragData = nullptr;
Expand All @@ -59,6 +60,7 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
fragColor0 = "fragColor0";
fragColor1 = "fragColor1";
texture = "texture";
texture3D = "texture";
texelFetch = "texelFetch";
bitwiseOps = true;
lastFragData = nullptr;
Expand All @@ -80,6 +82,7 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
glslVersionNumber = 450;
lastFragData = nullptr;
texture = "texture";
texture3D = "texture";
texelFetch = "texelFetch";
forceMatrix4x4 = false;
coefsFromBuffers = true;
Expand All @@ -102,6 +105,7 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
glslVersionNumber = 0;
lastFragData = nullptr;
texture = "texture";
texture3D = "texture";
texelFetch = "texelFetch";
forceMatrix4x4 = false;
coefsFromBuffers = true;
Expand Down
1 change: 1 addition & 0 deletions Common/GPU/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct ShaderLanguageDesc {
const char *fragColor0 = nullptr;
const char *fragColor1 = nullptr;
const char *texture = nullptr;
const char *texture3D = nullptr;
const char *texelFetch = nullptr;
const char *lastFragData = nullptr;
const char *framebufferFetchExtension = nullptr;
Expand Down
12 changes: 7 additions & 5 deletions Common/GPU/Vulkan/VulkanImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static bool IsDepthStencilFormat(VkFormat format) {
}
}

bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int depth, int numMips, VkFormat format, VkImageLayout initialLayout, VkImageUsageFlags usage, const VkComponentMapping *mapping) {
if (w == 0 || h == 0 || numMips == 0) {
ERROR_LOG(G3D, "Can't create a zero-size VulkanTexture");
return false;
Expand All @@ -41,17 +41,18 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,

width_ = w;
height_ = h;
depth_ = depth;
numMips_ = numMips;
format_ = format;

VkImageAspectFlags aspect = IsDepthStencilFormat(format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;

VkImageCreateInfo image_create_info{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.imageType = depth > 1 ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
image_create_info.format = format_;
image_create_info.extent.width = width_;
image_create_info.extent.height = height_;
image_create_info.extent.depth = 1;
image_create_info.extent.depth = depth;
image_create_info.mipLevels = numMips;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
Expand Down Expand Up @@ -98,7 +99,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
// Create the view while we're at it.
VkImageViewCreateInfo view_info{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
view_info.image = image_;
view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
view_info.viewType = depth > 1 ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
view_info.format = format_;
if (mapping) {
view_info.components = *mapping;
Expand All @@ -122,11 +123,12 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
}

// TODO: Batch these.
void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength) {
void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, int depthLayer, VkBuffer buffer, uint32_t offset, size_t rowLength) {
VkBufferImageCopy copy_region{};
copy_region.bufferOffset = offset;
copy_region.bufferRowLength = (uint32_t)rowLength;
copy_region.bufferImageHeight = 0; // 2D
copy_region.imageOffset.z = depthLayer;
copy_region.imageExtent.width = mipWidth;
copy_region.imageExtent.height = mipHeight;
copy_region.imageExtent.depth = 1;
Expand Down
Loading