diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index 08586d33ca..63d4491352 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <bitset>
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core.h"
@@ -49,6 +50,33 @@ void KeplerCompute::CallMethod(const GPU::MethodCall& method_call) {
     }
 }
 
+Tegra::Texture::FullTextureInfo KeplerCompute::GetTexture(std::size_t offset) const {
+    const std::bitset<8> cbuf_mask = launch_description.const_buffer_enable_mask.Value();
+    ASSERT(cbuf_mask[regs.tex_cb_index]);
+
+    const auto& texinfo = launch_description.const_buffer_config[regs.tex_cb_index];
+    ASSERT(texinfo.Address() != 0);
+
+    const GPUVAddr address = texinfo.Address() + offset * sizeof(Texture::TextureHandle);
+    ASSERT(address < texinfo.Address() + texinfo.size);
+
+    const Texture::TextureHandle tex_handle{memory_manager.Read<u32>(address)};
+    return GetTextureInfo(tex_handle, offset);
+}
+
+Texture::FullTextureInfo KeplerCompute::GetTextureInfo(const Texture::TextureHandle tex_handle,
+                                                       std::size_t offset) const {
+    return Texture::FullTextureInfo{static_cast<u32>(offset), GetTICEntry(tex_handle.tic_id),
+                                    GetTSCEntry(tex_handle.tsc_id)};
+}
+
+u32 KeplerCompute::AccessConstBuffer32(u64 const_buffer, u64 offset) const {
+    const auto& buffer = launch_description.const_buffer_config[const_buffer];
+    u32 result;
+    std::memcpy(&result, memory_manager.GetPointer(buffer.Address() + offset), sizeof(u32));
+    return result;
+}
+
 void KeplerCompute::ProcessLaunch() {
     const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address();
     memory_manager.ReadBlockUnsafe(launch_desc_loc, &launch_description,
@@ -60,4 +88,29 @@ void KeplerCompute::ProcessLaunch() {
     rasterizer.DispatchCompute(code_addr);
 }
 
+Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
+    const GPUVAddr tic_address_gpu{regs.tic.Address() + tic_index * sizeof(Texture::TICEntry)};
+
+    Texture::TICEntry tic_entry;
+    memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
+
+    const auto r_type{tic_entry.r_type.Value()};
+    const auto g_type{tic_entry.g_type.Value()};
+    const auto b_type{tic_entry.b_type.Value()};
+    const auto a_type{tic_entry.a_type.Value()};
+
+    // TODO(Subv): Different data types for separate components are not supported
+    DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
+
+    return tic_entry;
+}
+
+Texture::TSCEntry KeplerCompute::GetTSCEntry(u32 tsc_index) const {
+    const GPUVAddr tsc_address_gpu{regs.tsc.Address() + tsc_index * sizeof(Texture::TSCEntry)};
+
+    Texture::TSCEntry tsc_entry;
+    memory_manager.ReadBlockUnsafe(tsc_address_gpu, &tsc_entry, sizeof(Texture::TSCEntry));
+    return tsc_entry;
+}
+
 } // namespace Tegra::Engines
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index 6a3309a2c5..90cf650d2f 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -12,6 +12,7 @@
 #include "common/common_types.h"
 #include "video_core/engines/engine_upload.h"
 #include "video_core/gpu.h"
+#include "video_core/textures/texture.h"
 
 namespace Core {
 class System;
@@ -111,7 +112,7 @@ public:
 
                 INSERT_PADDING_WORDS(0x3FE);
 
-                u32 texture_const_buffer_index;
+                u32 tex_cb_index;
 
                 INSERT_PADDING_WORDS(0x374);
             };
@@ -149,7 +150,7 @@ public:
         union {
             BitField<0, 8, u32> const_buffer_enable_mask;
             BitField<29, 2, u32> cache_layout;
-        } memory_config;
+        };
 
         INSERT_PADDING_WORDS(0x8);
 
@@ -194,6 +195,14 @@ public:
     /// Write the value to the register identified by method.
     void CallMethod(const GPU::MethodCall& method_call);
 
+    Tegra::Texture::FullTextureInfo GetTexture(std::size_t offset) const;
+
+    /// Given a Texture Handle, returns the TSC and TIC entries.
+    Texture::FullTextureInfo GetTextureInfo(const Texture::TextureHandle tex_handle,
+                                            std::size_t offset) const;
+
+    u32 AccessConstBuffer32(u64 const_buffer, u64 offset) const;
+
 private:
     Core::System& system;
     VideoCore::RasterizerInterface& rasterizer;
@@ -201,6 +210,12 @@ private:
     Upload::State upload_state;
 
     void ProcessLaunch();
+
+    /// Retrieves information about a specific TIC entry from the TIC buffer.
+    Texture::TICEntry GetTICEntry(u32 tic_index) const;
+
+    /// Retrieves information about a specific TSC entry from the TSC buffer.
+    Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
 };
 
 #define ASSERT_REG_POSITION(field_name, position)                                                  \
@@ -218,12 +233,12 @@ ASSERT_REG_POSITION(launch, 0xAF);
 ASSERT_REG_POSITION(tsc, 0x557);
 ASSERT_REG_POSITION(tic, 0x55D);
 ASSERT_REG_POSITION(code_loc, 0x582);
-ASSERT_REG_POSITION(texture_const_buffer_index, 0x982);
+ASSERT_REG_POSITION(tex_cb_index, 0x982);
 ASSERT_LAUNCH_PARAM_POSITION(program_start, 0x8);
 ASSERT_LAUNCH_PARAM_POSITION(grid_dim_x, 0xC);
 ASSERT_LAUNCH_PARAM_POSITION(shared_alloc, 0x11);
 ASSERT_LAUNCH_PARAM_POSITION(block_dim_x, 0x12);
-ASSERT_LAUNCH_PARAM_POSITION(memory_config, 0x14);
+ASSERT_LAUNCH_PARAM_POSITION(const_buffer_enable_mask, 0x14);
 ASSERT_LAUNCH_PARAM_POSITION(const_buffer_config, 0x1D);
 
 #undef ASSERT_REG_POSITION
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0f09022590..5375ab9e06 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -801,6 +801,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
     }
 
     auto kernel = shader_cache.GetComputeKernel(code_addr);
+    SetupComputeImages(kernel);
+
     const auto [program, next_bindings] = kernel->GetProgramHandle({});
     state.draw.shader_program = program;
     state.draw.program_pipeline = 0;
@@ -922,7 +924,7 @@ void RasterizerOpenGL::SetupComputeConstBuffers(const Shader& kernel) {
     const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
     for (const auto& entry : kernel->GetShaderEntries().const_buffers) {
         const auto& config = launch_desc.const_buffer_config[entry.GetIndex()];
-        const std::bitset<8> mask = launch_desc.memory_config.const_buffer_enable_mask.Value();
+        const std::bitset<8> mask = launch_desc.const_buffer_enable_mask.Value();
         Tegra::Engines::ConstBufferInfo buffer;
         buffer.address = config.Address();
         buffer.size = config.size;
@@ -1038,6 +1040,24 @@ bool RasterizerOpenGL::SetupTexture(const Shader& shader, u32 binding,
     return false;
 }
 
+void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
+    const auto& compute = system.GPU().KeplerCompute();
+    const auto& entries = shader->GetShaderEntries().images;
+    for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
+        const auto& entry = entries[bindpoint];
+        const auto texture = [&]() {
+            if (!entry.IsBindless()) {
+                return compute.GetTexture(entry.GetOffset());
+            }
+            const auto cbuf = entry.GetBindlessCBuf();
+            Tegra::Texture::TextureHandle tex_handle;
+            tex_handle.raw = compute.AccessConstBuffer32(cbuf.first, cbuf.second);
+            return compute.GetTextureInfo(tex_handle, entry.GetOffset());
+        }();
+        UNIMPLEMENTED();
+    }
+}
+
 void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
     const auto& regs = system.GPU().Maxwell3D().regs;
     const bool geometry_shaders_enabled =
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 23ab7aff06..6fa1b7ec46 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -146,6 +146,8 @@ private:
                       const Tegra::Texture::FullTextureInfo& texture,
                       const GLShader::SamplerEntry& entry);
 
+    void SetupComputeImages(const Shader& shader);
+
     /// Syncs the viewport and depth range to match the guest state
     void SyncViewport(OpenGLState& current_state);
 
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 5db9313c48..0397f4c6e0 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -303,6 +303,10 @@ public:
         return is_bindless;
     }
 
+    std::pair<u32, u32> GetBindlessCBuf() const {
+        return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
+    }
+
     bool operator<(const Image& rhs) const {
         return std::tie(offset, index, type, is_bindless) <
                std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless);