diff options
Diffstat (limited to '')
4 files changed, 126 insertions, 38 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 61b6fe4b7..a40106c87 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -178,7 +178,10 @@ void ComputePipeline::Configure() { | |||
| 178 | for (const auto& desc : info.image_descriptors) { | 178 | for (const auto& desc : info.image_descriptors) { |
| 179 | for (u32 index = 0; index < desc.count; ++index) { | 179 | for (u32 index = 0; index < desc.count; ++index) { |
| 180 | ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | 180 | ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; |
| 181 | images[image_binding++] = image_view.Handle(desc.type); | 181 | if (desc.is_written) { |
| 182 | texture_cache.MarkModification(image_view.image_id); | ||
| 183 | } | ||
| 184 | images[image_binding++] = image_view.StorageView(desc.type, desc.format); | ||
| 182 | } | 185 | } |
| 183 | } | 186 | } |
| 184 | if (texture_binding != 0) { | 187 | if (texture_binding != 0) { |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index a5d65fdca..a2ea35d5a 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -332,7 +332,10 @@ void GraphicsPipeline::Configure(bool is_indexed) { | |||
| 332 | for (const auto& desc : info.image_descriptors) { | 332 | for (const auto& desc : info.image_descriptors) { |
| 333 | for (u32 index = 0; index < desc.count; ++index) { | 333 | for (u32 index = 0; index < desc.count; ++index) { |
| 334 | ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; | 334 | ImageView& image_view{texture_cache.GetImageView(*(views_it++))}; |
| 335 | images[image_binding++] = image_view.Handle(desc.type); | 335 | if (desc.is_written) { |
| 336 | texture_cache.MarkModification(image_view.image_id); | ||
| 337 | } | ||
| 338 | images[image_binding++] = image_view.StorageView(desc.type, desc.format); | ||
| 336 | } | 339 | } |
| 337 | } | 340 | } |
| 338 | }}; | 341 | }}; |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 7053be161..c373c9cb4 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -328,6 +328,28 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) { | |||
| 328 | } | 328 | } |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | [[nodiscard]] GLenum ShaderFormat(Shader::ImageFormat format) { | ||
| 332 | switch (format) { | ||
| 333 | case Shader::ImageFormat::Typeless: | ||
| 334 | break; | ||
| 335 | case Shader::ImageFormat::R8_SINT: | ||
| 336 | return GL_R8I; | ||
| 337 | case Shader::ImageFormat::R8_UINT: | ||
| 338 | return GL_R8UI; | ||
| 339 | case Shader::ImageFormat::R16_UINT: | ||
| 340 | return GL_R16UI; | ||
| 341 | case Shader::ImageFormat::R16_SINT: | ||
| 342 | return GL_R16I; | ||
| 343 | case Shader::ImageFormat::R32_UINT: | ||
| 344 | return GL_R32UI; | ||
| 345 | case Shader::ImageFormat::R32G32_UINT: | ||
| 346 | return GL_RG32UI; | ||
| 347 | case Shader::ImageFormat::R32G32B32A32_UINT: | ||
| 348 | return GL_RGBA32UI; | ||
| 349 | } | ||
| 350 | UNREACHABLE_MSG("Invalid image format={}", format); | ||
| 351 | return GL_R32UI; | ||
| 352 | } | ||
| 331 | } // Anonymous namespace | 353 | } // Anonymous namespace |
| 332 | 354 | ||
| 333 | ImageBufferMap::~ImageBufferMap() { | 355 | ImageBufferMap::~ImageBufferMap() { |
| @@ -837,21 +859,28 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 837 | } else { | 859 | } else { |
| 838 | internal_format = MaxwellToGL::GetFormatTuple(format).internal_format; | 860 | internal_format = MaxwellToGL::GetFormatTuple(format).internal_format; |
| 839 | } | 861 | } |
| 840 | VideoCommon::SubresourceRange flatten_range = info.range; | 862 | full_range = info.range; |
| 841 | std::array<GLuint, 2> handles; | 863 | flat_range = info.range; |
| 842 | stored_views.reserve(2); | 864 | set_object_label = device.HasDebuggingToolAttached(); |
| 843 | 865 | is_render_target = info.IsRenderTarget(); | |
| 866 | original_texture = image.texture.handle; | ||
| 867 | num_samples = image.info.num_samples; | ||
| 868 | if (!is_render_target) { | ||
| 869 | swizzle[0] = info.x_source; | ||
| 870 | swizzle[1] = info.y_source; | ||
| 871 | swizzle[2] = info.z_source; | ||
| 872 | swizzle[3] = info.w_source; | ||
| 873 | } | ||
| 844 | switch (info.type) { | 874 | switch (info.type) { |
| 845 | case ImageViewType::e1DArray: | 875 | case ImageViewType::e1DArray: |
| 846 | flatten_range.extent.layers = 1; | 876 | flat_range.extent.layers = 1; |
| 847 | [[fallthrough]]; | 877 | [[fallthrough]]; |
| 848 | case ImageViewType::e1D: | 878 | case ImageViewType::e1D: |
| 849 | glGenTextures(2, handles.data()); | 879 | SetupView(Shader::TextureType::Color1D); |
| 850 | SetupView(device, image, Shader::TextureType::Color1D, handles[0], info, flatten_range); | 880 | SetupView(Shader::TextureType::ColorArray1D); |
| 851 | SetupView(device, image, Shader::TextureType::ColorArray1D, handles[1], info, info.range); | ||
| 852 | break; | 881 | break; |
| 853 | case ImageViewType::e2DArray: | 882 | case ImageViewType::e2DArray: |
| 854 | flatten_range.extent.layers = 1; | 883 | flat_range.extent.layers = 1; |
| 855 | [[fallthrough]]; | 884 | [[fallthrough]]; |
| 856 | case ImageViewType::e2D: | 885 | case ImageViewType::e2D: |
| 857 | if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) { | 886 | if (True(flags & VideoCommon::ImageViewFlagBits::Slice)) { |
| @@ -861,26 +890,23 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI | |||
| 861 | .base = {.level = info.range.base.level, .layer = 0}, | 890 | .base = {.level = info.range.base.level, .layer = 0}, |
| 862 | .extent = {.levels = 1, .layers = 1}, | 891 | .extent = {.levels = 1, .layers = 1}, |
| 863 | }; | 892 | }; |
| 864 | glGenTextures(1, handles.data()); | 893 | full_range = slice_range; |
| 865 | SetupView(device, image, Shader::TextureType::Color3D, handles[0], info, slice_range); | 894 | |
| 895 | SetupView(Shader::TextureType::Color3D); | ||
| 866 | } else { | 896 | } else { |
| 867 | glGenTextures(2, handles.data()); | 897 | SetupView(Shader::TextureType::Color2D); |
| 868 | SetupView(device, image, Shader::TextureType::Color2D, handles[0], info, flatten_range); | 898 | SetupView(Shader::TextureType::ColorArray2D); |
| 869 | SetupView(device, image, Shader::TextureType::ColorArray2D, handles[1], info, | ||
| 870 | info.range); | ||
| 871 | } | 899 | } |
| 872 | break; | 900 | break; |
| 873 | case ImageViewType::e3D: | 901 | case ImageViewType::e3D: |
| 874 | glGenTextures(1, handles.data()); | 902 | SetupView(Shader::TextureType::Color3D); |
| 875 | SetupView(device, image, Shader::TextureType::Color3D, handles[0], info, info.range); | ||
| 876 | break; | 903 | break; |
| 877 | case ImageViewType::CubeArray: | 904 | case ImageViewType::CubeArray: |
| 878 | flatten_range.extent.layers = 6; | 905 | flat_range.extent.layers = 6; |
| 879 | [[fallthrough]]; | 906 | [[fallthrough]]; |
| 880 | case ImageViewType::Cube: | 907 | case ImageViewType::Cube: |
| 881 | glGenTextures(2, handles.data()); | 908 | SetupView(Shader::TextureType::ColorCube); |
| 882 | SetupView(device, image, Shader::TextureType::ColorCube, handles[0], info, flatten_range); | 909 | SetupView(Shader::TextureType::ColorArrayCube); |
| 883 | SetupView(device, image, Shader::TextureType::ColorArrayCube, handles[1], info, info.range); | ||
| 884 | break; | 910 | break; |
| 885 | case ImageViewType::Rect: | 911 | case ImageViewType::Rect: |
| 886 | UNIMPLEMENTED(); | 912 | UNIMPLEMENTED(); |
| @@ -928,22 +954,62 @@ ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, | |||
| 928 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) | 954 | ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageParams& params) |
| 929 | : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} | 955 | : VideoCommon::ImageViewBase{params}, views{runtime.null_image_views} {} |
| 930 | 956 | ||
| 931 | void ImageView::SetupView(const Device& device, Image& image, Shader::TextureType view_type, | 957 | GLuint ImageView::StorageView(Shader::TextureType texture_type, Shader::ImageFormat image_format) { |
| 932 | GLuint handle, const VideoCommon::ImageViewInfo& info, | 958 | if (image_format == Shader::ImageFormat::Typeless) { |
| 933 | VideoCommon::SubresourceRange view_range) { | 959 | return Handle(texture_type); |
| 934 | const GLuint parent = image.texture.handle; | 960 | } |
| 935 | const GLenum target = ImageTarget(view_type, image.info.num_samples); | 961 | const bool is_signed{image_format == Shader::ImageFormat::R8_SINT || |
| 936 | glTextureView(handle, target, parent, internal_format, view_range.base.level, | 962 | image_format == Shader::ImageFormat::R16_SINT}; |
| 963 | if (!storage_views) { | ||
| 964 | storage_views = std::make_unique<StorageViews>(); | ||
| 965 | } | ||
| 966 | auto& type_views{is_signed ? storage_views->signeds : storage_views->unsigneds}; | ||
| 967 | GLuint& view{type_views[static_cast<size_t>(texture_type)]}; | ||
| 968 | if (view == 0) { | ||
| 969 | view = MakeView(texture_type, ShaderFormat(image_format)); | ||
| 970 | } | ||
| 971 | return view; | ||
| 972 | } | ||
| 973 | |||
| 974 | void ImageView::SetupView(Shader::TextureType view_type) { | ||
| 975 | views[static_cast<size_t>(view_type)] = MakeView(view_type, internal_format); | ||
| 976 | } | ||
| 977 | |||
| 978 | GLuint ImageView::MakeView(Shader::TextureType view_type, GLenum view_format) { | ||
| 979 | VideoCommon::SubresourceRange view_range; | ||
| 980 | switch (view_type) { | ||
| 981 | case Shader::TextureType::Color1D: | ||
| 982 | case Shader::TextureType::Color2D: | ||
| 983 | case Shader::TextureType::ColorCube: | ||
| 984 | view_range = flat_range; | ||
| 985 | break; | ||
| 986 | case Shader::TextureType::ColorArray1D: | ||
| 987 | case Shader::TextureType::ColorArray2D: | ||
| 988 | case Shader::TextureType::Color3D: | ||
| 989 | case Shader::TextureType::ColorArrayCube: | ||
| 990 | view_range = full_range; | ||
| 991 | break; | ||
| 992 | default: | ||
| 993 | UNREACHABLE(); | ||
| 994 | } | ||
| 995 | OGLTextureView& view = stored_views.emplace_back(); | ||
| 996 | view.Create(); | ||
| 997 | |||
| 998 | const GLenum target = ImageTarget(view_type, num_samples); | ||
| 999 | glTextureView(view.handle, target, original_texture, view_format, view_range.base.level, | ||
| 937 | view_range.extent.levels, view_range.base.layer, view_range.extent.layers); | 1000 | view_range.extent.levels, view_range.base.layer, view_range.extent.layers); |
| 938 | if (!info.IsRenderTarget()) { | 1001 | if (!is_render_target) { |
| 939 | ApplySwizzle(handle, format, info.Swizzle()); | 1002 | std::array<SwizzleSource, 4> casted_swizzle; |
| 1003 | std::ranges::transform(swizzle, casted_swizzle.begin(), [](u8 component_swizzle) { | ||
| 1004 | return static_cast<SwizzleSource>(component_swizzle); | ||
| 1005 | }); | ||
| 1006 | ApplySwizzle(view.handle, format, casted_swizzle); | ||
| 940 | } | 1007 | } |
| 941 | if (device.HasDebuggingToolAttached()) { | 1008 | if (set_object_label) { |
| 942 | const std::string name = VideoCommon::Name(*this); | 1009 | const std::string name = VideoCommon::Name(*this); |
| 943 | glObjectLabel(GL_TEXTURE, handle, static_cast<GLsizei>(name.size()), name.data()); | 1010 | glObjectLabel(GL_TEXTURE, view.handle, static_cast<GLsizei>(name.size()), name.data()); |
| 944 | } | 1011 | } |
| 945 | stored_views.emplace_back().handle = handle; | 1012 | return view.handle; |
| 946 | views[static_cast<size_t>(view_type)] = handle; | ||
| 947 | } | 1013 | } |
| 948 | 1014 | ||
| 949 | Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) { | 1015 | Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) { |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 2e3e02b79..921072ebe 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -185,6 +185,9 @@ public: | |||
| 185 | const VideoCommon::ImageViewInfo& view_info); | 185 | const VideoCommon::ImageViewInfo& view_info); |
| 186 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); | 186 | explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageParams&); |
| 187 | 187 | ||
| 188 | [[nodiscard]] GLuint StorageView(Shader::TextureType texture_type, | ||
| 189 | Shader::ImageFormat image_format); | ||
| 190 | |||
| 188 | [[nodiscard]] GLuint Handle(Shader::TextureType handle_type) const noexcept { | 191 | [[nodiscard]] GLuint Handle(Shader::TextureType handle_type) const noexcept { |
| 189 | return views[static_cast<size_t>(handle_type)]; | 192 | return views[static_cast<size_t>(handle_type)]; |
| 190 | } | 193 | } |
| @@ -206,16 +209,29 @@ public: | |||
| 206 | } | 209 | } |
| 207 | 210 | ||
| 208 | private: | 211 | private: |
| 209 | void SetupView(const Device& device, Image& image, Shader::TextureType view_type, GLuint handle, | 212 | struct StorageViews { |
| 210 | const VideoCommon::ImageViewInfo& info, | 213 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> signeds{}; |
| 211 | VideoCommon::SubresourceRange view_range); | 214 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> unsigneds{}; |
| 215 | }; | ||
| 216 | |||
| 217 | void SetupView(Shader::TextureType view_type); | ||
| 218 | |||
| 219 | GLuint MakeView(Shader::TextureType view_type, GLenum view_format); | ||
| 212 | 220 | ||
| 213 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> views{}; | 221 | std::array<GLuint, Shader::NUM_TEXTURE_TYPES> views{}; |
| 214 | std::vector<OGLTextureView> stored_views; | 222 | std::vector<OGLTextureView> stored_views; |
| 223 | std::unique_ptr<StorageViews> storage_views; | ||
| 215 | GLenum internal_format = GL_NONE; | 224 | GLenum internal_format = GL_NONE; |
| 216 | GLuint default_handle = 0; | 225 | GLuint default_handle = 0; |
| 217 | GPUVAddr gpu_addr = 0; | 226 | GPUVAddr gpu_addr = 0; |
| 218 | u32 buffer_size = 0; | 227 | u32 buffer_size = 0; |
| 228 | GLuint original_texture = 0; | ||
| 229 | int num_samples = 0; | ||
| 230 | VideoCommon::SubresourceRange flat_range; | ||
| 231 | VideoCommon::SubresourceRange full_range; | ||
| 232 | std::array<u8, 4> swizzle{}; | ||
| 233 | bool set_object_label = false; | ||
| 234 | bool is_render_target = false; | ||
| 219 | }; | 235 | }; |
| 220 | 236 | ||
| 221 | class ImageAlloc : public VideoCommon::ImageAllocBase {}; | 237 | class ImageAlloc : public VideoCommon::ImageAllocBase {}; |