diff --git a/src/dxvk/dxvk_barrier.cpp b/src/dxvk/dxvk_barrier.cpp
index 29f19f2c..ce1cf033 100644
--- a/src/dxvk/dxvk_barrier.cpp
+++ b/src/dxvk/dxvk_barrier.cpp
@@ -33,6 +33,29 @@ namespace dxvk {
   }
   
   
+  void DxvkBarrierSet::initImage(
+    const Rc<DxvkImage>&            image,
+    const VkImageSubresourceRange&  subresources,
+          VkImageLayout             dstLayout,
+          VkPipelineStageFlags      dstStages,
+          VkAccessFlags             dstAccess) {
+    m_dstStages |= dstStages;
+    
+    VkImageMemoryBarrier barrier;
+    barrier.sType                 = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+    barrier.pNext                 = nullptr;
+    barrier.srcAccessMask         = 0;
+    barrier.dstAccessMask         = dstAccess;
+    barrier.oldLayout             = VK_IMAGE_LAYOUT_UNDEFINED;
+    barrier.newLayout             = dstLayout;
+    barrier.srcQueueFamilyIndex   = VK_QUEUE_FAMILY_IGNORED;
+    barrier.dstQueueFamilyIndex   = VK_QUEUE_FAMILY_IGNORED;
+    barrier.image                 = image->handle();
+    barrier.subresourceRange      = subresources;
+    m_imgBarriers.push_back(barrier);
+  }
+  
+  
   void DxvkBarrierSet::recordCommands(const Rc<DxvkCommandList>& commandList) {
     if ((m_srcStages | m_dstStages) != 0) {
       VkPipelineStageFlags srcFlags = m_srcStages;
diff --git a/src/dxvk/dxvk_barrier.h b/src/dxvk/dxvk_barrier.h
index 0423c89f..ac08a6a2 100644
--- a/src/dxvk/dxvk_barrier.h
+++ b/src/dxvk/dxvk_barrier.h
@@ -27,6 +27,13 @@ namespace dxvk {
             VkPipelineStageFlags      stages,
             VkAccessFlags             access);
     
+    void initImage(
+      const Rc<DxvkImage>&            image,
+      const VkImageSubresourceRange&  subresources,
+            VkImageLayout             dstLayout,
+            VkPipelineStageFlags      dstStages,
+            VkAccessFlags             dstAccess);
+    
     void recordCommands(
       const Rc<DxvkCommandList>&      commandList);
     
diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp
index e652981a..f7c7316f 100644
--- a/src/dxvk/dxvk_context.cpp
+++ b/src/dxvk/dxvk_context.cpp
@@ -203,6 +203,35 @@ namespace dxvk {
   }
   
   
+  void DxvkContext::initBuffer(
+    const Rc<DxvkBuffer>&     buffer,
+    const Rc<DxvkDataBuffer>& data) {
+    // TODO implement
+  }
+  
+  
+  void DxvkContext::initImage(
+    const Rc<DxvkImage>&      image,
+    const Rc<DxvkDataBuffer>& data) {
+    const DxvkImageCreateInfo& info = image->info();
+    
+    VkImageSubresourceRange sr;
+    sr.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
+    sr.baseMipLevel   = 0;
+    sr.levelCount     = info.mipLevels;
+    sr.baseArrayLayer = 0;
+    sr.levelCount     = info.numLayers;
+    
+    m_barriers.initImage(image, sr,
+      VK_IMAGE_LAYOUT_GENERAL,
+      info.stages,
+      info.access);
+    m_barriers.recordCommands(m_cmd);
+    
+    // TODO implement data upload
+  }
+  
+  
   void DxvkContext::setViewports(
           uint32_t            viewportCount,
     const VkViewport*         viewports,
diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h
index c8f0f2c9..c5a2c142 100644
--- a/src/dxvk/dxvk_context.h
+++ b/src/dxvk/dxvk_context.h
@@ -3,6 +3,7 @@
 #include "dxvk_barrier.h"
 #include "dxvk_cmdlist.h"
 #include "dxvk_context_state.h"
+#include "dxvk_data.h"
 #include "dxvk_pipemgr.h"
 #include "dxvk_util.h"
 
@@ -166,6 +167,33 @@ namespace dxvk {
             uint32_t vertexOffset,
             uint32_t firstInstance);
     
+    /**
+     * \brief Initializes a buffer
+     * 
+     * Uploads initial data to the buffer so that it
+     * can be used for read-only operations. Unlike
+     * \ref initImage, calling this is optional.
+     * \param [in] buffer The buffer to initialize
+     * \param [in] data Initial data buffer
+     */
+    void initBuffer(
+      const Rc<DxvkBuffer>&     buffer,
+      const Rc<DxvkDataBuffer>& data);
+    
+    /**
+     * \brief Initializes an image
+     * 
+     * Sets up the image layout for future operations
+     * and uploads data to the image. Note that this
+     * method \e must be executed on the GPU before
+     * the image can be used for any other operations.
+     * \param [in] image The image to initialize
+     * \param [in] data Initial data. Can be omitted.
+     */
+    void initImage(
+      const Rc<DxvkImage>&      image,
+      const Rc<DxvkDataBuffer>& data);
+    
     /**
      * \brief Sets viewports
      * 
diff --git a/src/dxvk/dxvk_data.cpp b/src/dxvk/dxvk_data.cpp
new file mode 100644
index 00000000..1b5af889
--- /dev/null
+++ b/src/dxvk/dxvk_data.cpp
@@ -0,0 +1,17 @@
+#include <cstring>
+
+#include "dxvk_data.h"
+
+namespace dxvk {
+  
+  DxvkDataBuffer:: DxvkDataBuffer() { }
+  DxvkDataBuffer::~DxvkDataBuffer() { }
+  
+  DxvkDataBuffer::DxvkDataBuffer(
+    const void*   data,
+          size_t  size) {
+    m_data.resize(size);
+    std::memcpy(m_data.data(), data, size);
+  }
+  
+}
\ No newline at end of file
diff --git a/src/dxvk/dxvk_data.h b/src/dxvk/dxvk_data.h
new file mode 100644
index 00000000..faa26b8a
--- /dev/null
+++ b/src/dxvk/dxvk_data.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "dxvk_include.h"
+
+namespace dxvk {
+  
+  /**
+   * \brief Data buffer
+   * 
+   * Stores immutable data. Used for temporary
+   * copies of data that can be transferred to
+   * or from DXVK resources.
+   */
+  class DxvkDataBuffer : public RcObject {
+    
+  public:
+    
+    DxvkDataBuffer();
+    DxvkDataBuffer(
+      const void*   data,
+            size_t  size);
+    ~DxvkDataBuffer();
+    
+    size_t size() const {
+      return m_data.size();
+    }
+    
+    void* data() {
+      return m_data.data();
+    }
+    
+    const void* data() const {
+      return m_data.data();
+    }
+    
+  private:
+    
+    std::vector<char> m_data;
+    
+  };
+  
+}
\ No newline at end of file
diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build
index 2bfe6382..a06fbf47 100644
--- a/src/dxvk/meson.build
+++ b/src/dxvk/meson.build
@@ -6,6 +6,7 @@ dxvk_src = files([
   'dxvk_compute.cpp',
   'dxvk_constant_state.cpp',
   'dxvk_context.cpp',
+  'dxvk_data.cpp',
   'dxvk_descriptor.cpp',
   'dxvk_device.cpp',
   'dxvk_framebuffer.cpp',