gl_texture_cache: Create image storage views

Fixes SULD.D tests.
This commit is contained in:
ReinUsesLisp 2021-06-07 20:43:00 -03:00 committed by ameerj
parent b1ed64ac18
commit 7eaa74ad23
4 changed files with 126 additions and 38 deletions

View file

@ -178,7 +178,10 @@ void ComputePipeline::Configure() {
for (const auto& desc : info.image_descriptors) { for (const auto& desc : info.image_descriptors) {
for (u32 index = 0; index < desc.count; ++index) { for (u32 index = 0; index < desc.count; ++index) {
ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; ImageView& image_view{texture_cache.GetImageView(*(views_it++))};
images[image_binding++] = image_view.Handle(desc.type); if (desc.is_written) {
texture_cache.MarkModification(image_view.image_id);
}
images[image_binding++] = image_view.StorageView(desc.type, desc.format);
} }
} }
if (texture_binding != 0) { if (texture_binding != 0) {

View file

@ -332,7 +332,10 @@ void GraphicsPipeline::Configure(bool is_indexed) {
for (const auto& desc : info.image_descriptors) { for (const auto& desc : info.image_descriptors) {
for (u32 index = 0; index < desc.count; ++index) { for (u32 index = 0; index < desc.count; ++index) {
ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; ImageView& image_view{texture_cache.GetImageView(*(views_it++))};
images[image_binding++] = image_view.Handle(desc.type); if (desc.is_written) {
texture_cache.MarkModification(image_view.image_id);
}
images[image_binding++] = image_view.StorageView(desc.type, desc.format);
} }
} }
}}; }};

View file

@ -328,6 +328,28 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
} }
} }
[[nodiscard]] GLenum ShaderFormat(Shader::ImageFormat format) {
switch (format) {
case Shader::ImageFormat::Typeless:
break;
case Shader::ImageFormat::R8_SINT:
return GL_R8I;
case Shader::ImageFormat::R8_UINT:
return GL_R8UI;
case Shader::ImageFormat::R16_UINT:
return GL_R16UI;
case Shader::ImageFormat::R16_SINT:
return GL_R16I;
case Shader::ImageFormat::R32_UINT:
return GL_R32UI;
case Shader::ImageFormat::R32G32_UINT:
return GL_RG32UI;
case Shader::ImageFormat::R32G32B32A32_UINT:
return GL_RGBA32UI;
}
UNREACHABLE_MSG("Invalid image format={}", format);
return GL_R32UI;
}
} // Anonymous namespace } // Anonymous namespace
ImageBufferMap::~ImageBufferMap() { ImageBufferMap::~ImageBufferMap() {
@ -837,21 +859,28 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
} else { } else {
internal_format = MaxwellToGL::GetFormatTuple(format).internal_format; internal_format = MaxwellToGL::GetFormatTuple(format).internal_format;
} }
VideoCommon::SubresourceRange flatten_range = info.range; full_range = info.range;
std::array<GLuint, 2> handles; flat_range = info.range;
stored_views.reserve(2); set_object_label = device.HasDebuggingToolAttached();
is_render_target = info.IsRenderTarget();
original_texture = image.texture.handle;
num_samples = image.info.num_samples;
if (!is_render_target) {
swizzle[0] = info.x_source;
swizzle[1] = info.y_source;
swizzle[2] = info.z_source;
swizzle[3] = info.w_source;
}
switch (info.type) { switch (info.type) {
case ImageViewType::e1DArray: case ImageViewType::e1DArray:
flatten_range.extent.layers = 1; flat_range.extent.layers = 1;
[[fallthrough]]; [[fallthrough]];
case ImageViewType::e1D: case ImageViewType::e1D:
glGenTextures(2, handles.data()); SetupView(Shader::TextureType::Color1D);
SetupView(device, image, Shader::TextureType::Color1D, handles[0], info, flatten_range); SetupView(Shader::TextureType::ColorArray1D);
SetupView(device, image, Shader::TextureType::ColorArray1D, handles[1], info, info.range);
break; break;
case ImageViewType::e2DArray: case ImageViewType::e2DArray:
flatten_range.extent.layers = 1; flat_range.extent.layers = 1;
[[fallthrough]]; [[fallthrough]];
case ImageViewType::e2D: case ImageViewType::e2D:
if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) { if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) {
@ -861,26 +890,23 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
.base = {.level = info.range.base.level, .layer = 0}, .base = {.level = info.range.base.level, .layer = 0},
.extent = {.levels = 1, .layers = 1}, .extent = {.levels = 1, .layers = 1},
}; };
glGenTextures(1, handles.data()); full_range = slice_range;
SetupView(device, image, Shader::TextureType::Color3D, handles[0], info, slice_range);
SetupView(Shader::TextureType::Color3D);
} else { } else {
glGenTextures(2, handles.data()); SetupView(Shader::TextureType::Color2D);
SetupView(device, image, Shader::TextureType::Color2D, handles[0], info, flatten_range); SetupView(Shader::TextureType::ColorArray2D);
SetupView(device, image, Shader::TextureType::ColorArray2D, handles[1], info,
info.range);
} }
break; break;
case ImageViewType::e3D: case ImageViewType::e3D:
glGenTextures(1, handles.data()); SetupView(Shader::TextureType::Color3D);
SetupView(device, image, Shader::TextureType::Color3D, handles[0], info, info.range);
break; break;
case ImageViewType::CubeArray: case ImageViewType::CubeArray:
flatten_range.extent.layers = 6; flat_range.extent.layers = 6;
[[fallthrough]]; [[fallthrough]];
case ImageViewType::Cube: case ImageViewType::Cube:
glGenTextures(2, handles.data()); SetupView(Shader::TextureType::ColorCube);
SetupView(device, image, Shader::TextureType::ColorCube, handles[0], info, flatten_range); SetupView(Shader::TextureType::ColorArrayCube);
SetupView(device, image, Shader::TextureType::ColorArrayCube, handles[1], info, info.range);
break; break;
case ImageViewType::Rect: case ImageViewType::Rect:
UNIMPLEMENTED(); UNIMPLEMENTED();
@ -928,22 +954,62 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params)
: VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {}
void ImageView::SetupView(const Device& device, Image& image, Shader::TextureType view_type, GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) {
GLuint handle, const VideoCommon::ImageViewInfo& info, if (image_format == Shader::ImageFormat::Typeless) {
VideoCommon::SubresourceRange view_range) { return Handle(texture_type);
const GLuint parent = image.texture.handle; }
const GLenum target = ImageTarget(view_type, image.info.num_samples); const bool is_signed{image_format == Shader::ImageFormat::R8_SINT ||
glTextureView(handle, target, parent, internal_format, view_range.base.level, image_format == Shader::ImageFormat::R16_SINT};
if (!storage_views) {
storage_views = std::make_unique<StorageViews>();
}
auto& type_views{is_signed ? storage_views->signeds : storage_views->unsigneds};
GLuint& view{type_views[static_cast<size_t>(texture_type)]};
if (view == 0) {
view = MakeView(texture_type, ShaderFormat(image_format));
}
return view;
}
void ImageView::SetupView(Shader::TextureType view_type) {
views[static_cast<size_t>(view_type)] = MakeView(view_type, internal_format);
}
GLuint ImageView::MakeView(Shader::TextureType view_type, GLenum view_format) {
VideoCommon::SubresourceRange view_range;
switch (view_type) {
case Shader::TextureType::Color1D:
case Shader::TextureType::Color2D:
case Shader::TextureType::ColorCube:
view_range = flat_range;
break;
case Shader::TextureType::ColorArray1D:
case Shader::TextureType::ColorArray2D:
case Shader::TextureType::Color3D:
case Shader::TextureType::ColorArrayCube:
view_range = full_range;
break;
default:
UNREACHABLE();
}
OGLTextureView& view = stored_views.emplace_back();
view.Create();
const GLenum target = ImageTarget(view_type, num_samples);
glTextureView(view.handle, target, original_texture, view_format, view_range.base.level,
view_range.extent.levels, view_range.base.layer, view_range.extent.layers); view_range.extent.levels, view_range.base.layer, view_range.extent.layers);
if (!info.IsRenderTarget()) { if (!is_render_target) {
ApplySwizzle(handle, format, info.Swizzle()); std::array<SwizzleSource, 4> casted_swizzle;
std::ranges::transform(swizzle, casted_swizzle.begin(), [](u8 component_swizzle) {
return static_cast<SwizzleSource>(component_swizzle);
});
ApplySwizzle(view.handle, format, casted_swizzle);
} }
if (device.HasDebuggingToolAttached()) { if (set_object_label) {
const std::string name = VideoCommon::Name(*this); const std::string name = VideoCommon::Name(*this);
glObjectLabel(GL_TEXTURE, handle, static_cast<GLsizei>(name.size()), name.data()); glObjectLabel(GL_TEXTURE, view.handle, static_cast<GLsizei>(name.size()), name.data());
} }
stored_views.emplace_back().handle = handle; return view.handle;
views[static_cast<size_t>(view_type)] = handle;
} }
Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) { Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) {

View file

@ -185,6 +185,9 @@ public:
const VideoCommon::ImageViewInfo& view_info); const VideoCommon::ImageViewInfo& view_info);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&);
[[nodiscard]] GLuint StorageView(Shader::TextureType texture_type,
Shader::ImageFormat image_format);
[[nodiscard]] GLuint Handle(Shader::TextureType handle_type) const noexcept { [[nodiscard]] GLuint Handle(Shader::TextureType handle_type) const noexcept {
return views[static_cast<size_t>(handle_type)]; return views[static_cast<size_t>(handle_type)];
} }
@ -206,16 +209,29 @@ public:
} }
private: private:
void SetupView(const Device& device, Image& image, Shader::TextureType view_type, GLuint handle, struct StorageViews {
const VideoCommon::ImageViewInfo& info, std::array<GLuint, Shader::NUM_TEXTURE_TYPES> signeds{};
VideoCommon::SubresourceRange view_range); std::array<GLuint, Shader::NUM_TEXTURE_TYPES> unsigneds{};
};
void SetupView(Shader::TextureType view_type);
GLuint MakeView(Shader::TextureType view_type, GLenum view_format);
std::array<GLuint, Shader::NUM_TEXTURE_TYPES> views{}; std::array<GLuint, Shader::NUM_TEXTURE_TYPES> views{};
std::vector<OGLTextureView> stored_views; std::vector<OGLTextureView> stored_views;
std::unique_ptr<StorageViews> storage_views;
GLenum internal_format = GL_NONE; GLenum internal_format = GL_NONE;
GLuint default_handle = 0; GLuint default_handle = 0;
GPUVAddr gpu_addr = 0; GPUVAddr gpu_addr = 0;
u32 buffer_size = 0; u32 buffer_size = 0;
GLuint original_texture = 0;
int num_samples = 0;
VideoCommon::SubresourceRange flat_range;
VideoCommon::SubresourceRange full_range;
std::array<u8, 4> swizzle{};
bool set_object_label = false;
bool is_render_target = false;
}; };
class ImageAlloc : public VideoCommon::ImageAllocBase {}; class ImageAlloc : public VideoCommon::ImageAllocBase {};