Purge more unused
This commit is contained in:
parent
ba4eeb5e94
commit
7d7a06b9f7
|
@ -33,11 +33,7 @@
|
|||
<ClCompile Include="cpu_types.cpp" />
|
||||
<ClCompile Include="digital_controller.cpp" />
|
||||
<ClCompile Include="game_database.cpp" />
|
||||
<ClCompile Include="gpu\d3d11\shader_cache.cpp" />
|
||||
<ClCompile Include="gpu\d3d11\shader_compiler.cpp" />
|
||||
<ClCompile Include="gpu\d3d11\stream_buffer.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_device.cpp" />
|
||||
<ClCompile Include="gpu\d3d11_texture.cpp" />
|
||||
<ClCompile Include="gpu\d3d12\context.cpp" />
|
||||
<ClCompile Include="gpu\d3d12\descriptor_heap_manager.cpp" />
|
||||
<ClCompile Include="gpu\d3d12\shader_cache.cpp" />
|
||||
|
@ -158,12 +154,8 @@
|
|||
</ClInclude>
|
||||
<ClInclude Include="digital_controller.h" />
|
||||
<ClInclude Include="game_database.h" />
|
||||
<ClInclude Include="gpu\d3d11\shader_cache.h" />
|
||||
<ClInclude Include="gpu\d3d11\shader_compiler.h" />
|
||||
<ClInclude Include="gpu\d3d11\stream_buffer.h" />
|
||||
<ClInclude Include="gpu\d3d11_device.h" />
|
||||
<ClInclude Include="gpu\d3d_shaders.h" />
|
||||
<ClInclude Include="gpu\d3d11_texture.h" />
|
||||
<ClInclude Include="gpu\d3d12\context.h" />
|
||||
<ClInclude Include="gpu\d3d12\descriptor_heap_manager.h" />
|
||||
<ClInclude Include="gpu\d3d12\shader_cache.h" />
|
||||
|
|
|
@ -74,15 +74,6 @@
|
|||
<ClCompile Include="gpu\vulkan_gpu_device.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11\stream_buffer.cpp">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11\shader_cache.cpp">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11\shader_compiler.cpp">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d12\shader_cache.cpp">
|
||||
<Filter>gpu\d3d12</Filter>
|
||||
</ClCompile>
|
||||
|
@ -185,9 +176,6 @@
|
|||
<ClCompile Include="gpu\gpu_texture.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\d3d11_texture.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gpu\gpu_shader_cache.cpp">
|
||||
<Filter>gpu</Filter>
|
||||
</ClCompile>
|
||||
|
@ -272,15 +260,6 @@
|
|||
<ClInclude Include="gpu\vulkan_gpu_device.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11\shader_compiler.h">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11\stream_buffer.h">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11\shader_cache.h">
|
||||
<Filter>gpu\d3d11</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d12\shader_cache.h">
|
||||
<Filter>gpu\d3d12</Filter>
|
||||
</ClInclude>
|
||||
|
@ -392,9 +371,6 @@
|
|||
<ClInclude Include="gpu\gpu_texture.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d11_texture.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gpu\d3d_shaders.h">
|
||||
<Filter>gpu</Filter>
|
||||
</ClInclude>
|
||||
|
@ -406,9 +382,6 @@
|
|||
<Filter Include="gpu">
|
||||
<UniqueIdentifier>{7b18fac1-ee2b-4816-8537-eb8f32d40ada}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="gpu\d3d11">
|
||||
<UniqueIdentifier>{f5b7a4af-72c7-406f-b787-9036115c3580}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="gpu\d3d12">
|
||||
<UniqueIdentifier>{17c2f89b-5cf4-4d3a-9343-a03c1c668b85}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
|
|
@ -1,307 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "shader_cache.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/md5_digest.h"
|
||||
#include "shader_compiler.h"
|
||||
#include <d3dcompiler.h>
|
||||
Log_SetChannel(D3D11::ShaderCache);
|
||||
|
||||
namespace D3D11 {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct CacheIndexEntry
|
||||
{
|
||||
u64 source_hash_low;
|
||||
u64 source_hash_high;
|
||||
u32 source_length;
|
||||
u32 shader_type;
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
ShaderCache::ShaderCache() = default;
|
||||
|
||||
ShaderCache::~ShaderCache()
|
||||
{
|
||||
if (m_index_file)
|
||||
std::fclose(m_index_file);
|
||||
if (m_blob_file)
|
||||
std::fclose(m_blob_file);
|
||||
}
|
||||
|
||||
bool ShaderCache::CacheIndexKey::operator==(const CacheIndexKey& key) const
|
||||
{
|
||||
return (source_hash_low == key.source_hash_low && source_hash_high == key.source_hash_high &&
|
||||
source_length == key.source_length && shader_type == key.shader_type);
|
||||
}
|
||||
|
||||
bool ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
|
||||
{
|
||||
return (source_hash_low != key.source_hash_low || source_hash_high != key.source_hash_high ||
|
||||
source_length != key.source_length || shader_type != key.shader_type);
|
||||
}
|
||||
|
||||
void ShaderCache::Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug)
|
||||
{
|
||||
m_feature_level = feature_level;
|
||||
m_version = version;
|
||||
m_debug = debug;
|
||||
|
||||
if (!base_path.empty())
|
||||
{
|
||||
const std::string base_filename = GetCacheBaseFileName(base_path, feature_level, debug);
|
||||
const std::string index_filename = base_filename + ".idx";
|
||||
const std::string blob_filename = base_filename + ".bin";
|
||||
|
||||
if (!ReadExisting(index_filename, blob_filename))
|
||||
CreateNew(index_filename, blob_filename);
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderCache::CreateNew(const std::string& index_filename, const std::string& blob_filename)
|
||||
{
|
||||
if (FileSystem::FileExists(index_filename.c_str()))
|
||||
{
|
||||
Log_WarningPrintf("Removing existing index file '%s'", index_filename.c_str());
|
||||
FileSystem::DeleteFile(index_filename.c_str());
|
||||
}
|
||||
if (FileSystem::FileExists(blob_filename.c_str()))
|
||||
{
|
||||
Log_WarningPrintf("Removing existing blob file '%s'", blob_filename.c_str());
|
||||
FileSystem::DeleteFile(blob_filename.c_str());
|
||||
}
|
||||
|
||||
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "wb");
|
||||
if (!m_index_file)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to open index file '%s' for writing", index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 index_version = FILE_VERSION;
|
||||
if (std::fwrite(&index_version, sizeof(index_version), 1, m_index_file) != 1 ||
|
||||
std::fwrite(&m_version, sizeof(m_version), 1, m_index_file) != 1)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to write version to index file '%s'", index_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
FileSystem::DeleteFile(index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "w+b");
|
||||
if (!m_blob_file)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to open blob file '%s' for writing", blob_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
FileSystem::DeleteFile(index_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShaderCache::ReadExisting(const std::string& index_filename, const std::string& blob_filename)
|
||||
{
|
||||
m_index_file = FileSystem::OpenCFile(index_filename.c_str(), "r+b");
|
||||
if (!m_index_file)
|
||||
return false;
|
||||
|
||||
u32 file_version = 0;
|
||||
u32 data_version = 0;
|
||||
if (std::fread(&file_version, sizeof(file_version), 1, m_index_file) != 1 || file_version != FILE_VERSION ||
|
||||
std::fread(&data_version, sizeof(data_version), 1, m_index_file) != 1 || data_version != m_version)
|
||||
{
|
||||
Log_ErrorPrintf("Bad file/data version in '%s'", index_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_blob_file = FileSystem::OpenCFile(blob_filename.c_str(), "a+b");
|
||||
if (!m_blob_file)
|
||||
{
|
||||
Log_ErrorPrintf("Blob file '%s' is missing", blob_filename.c_str());
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::fseek(m_blob_file, 0, SEEK_END);
|
||||
const u32 blob_file_size = static_cast<u32>(std::ftell(m_blob_file));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CacheIndexEntry entry;
|
||||
if (std::fread(&entry, sizeof(entry), 1, m_index_file) != 1 ||
|
||||
(entry.file_offset + entry.blob_size) > blob_file_size)
|
||||
{
|
||||
if (std::feof(m_index_file))
|
||||
break;
|
||||
|
||||
Log_ErrorPrintf("Failed to read entry from '%s', corrupt file?", index_filename.c_str());
|
||||
m_index.clear();
|
||||
std::fclose(m_blob_file);
|
||||
m_blob_file = nullptr;
|
||||
std::fclose(m_index_file);
|
||||
m_index_file = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
const CacheIndexKey key{entry.source_hash_low, entry.source_hash_high, entry.source_length,
|
||||
static_cast<ShaderCompiler::Type>(entry.shader_type)};
|
||||
const CacheIndexData data{entry.file_offset, entry.blob_size};
|
||||
m_index.emplace(key, data);
|
||||
}
|
||||
|
||||
// ensure we don't write before seeking
|
||||
std::fseek(m_index_file, 0, SEEK_END);
|
||||
|
||||
Log_InfoPrintf("Read %zu entries from '%s'", m_index.size(), index_filename.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ShaderCache::GetCacheBaseFileName(const std::string_view& base_path, D3D_FEATURE_LEVEL feature_level,
|
||||
bool debug)
|
||||
{
|
||||
std::string base_filename(base_path);
|
||||
base_filename += FS_OSPATH_SEPARATOR_STR "d3d_shaders_";
|
||||
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
base_filename += "sm40";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
base_filename += "sm41";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
base_filename += "sm50";
|
||||
break;
|
||||
default:
|
||||
base_filename += "unk";
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
base_filename += "_debug";
|
||||
|
||||
return base_filename;
|
||||
}
|
||||
|
||||
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(ShaderCompiler::Type type, const std::string_view& shader_code)
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u64 hash_low;
|
||||
u64 hash_high;
|
||||
};
|
||||
u8 hash[16];
|
||||
};
|
||||
|
||||
MD5Digest digest;
|
||||
digest.Update(shader_code.data(), static_cast<u32>(shader_code.length()));
|
||||
digest.Final(hash);
|
||||
|
||||
return CacheIndexKey{hash_low, hash_high, static_cast<u32>(shader_code.length()), type};
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3DBlob> ShaderCache::GetShaderBlob(ShaderCompiler::Type type, std::string_view shader_code)
|
||||
{
|
||||
const auto key = GetCacheKey(type, shader_code);
|
||||
auto iter = m_index.find(key);
|
||||
if (iter == m_index.end())
|
||||
return CompileAndAddShaderBlob(key, shader_code);
|
||||
|
||||
ComPtr<ID3DBlob> blob;
|
||||
HRESULT hr = D3DCreateBlob(iter->second.blob_size, blob.GetAddressOf());
|
||||
if (FAILED(hr) || std::fseek(m_blob_file, iter->second.file_offset, SEEK_SET) != 0 ||
|
||||
std::fread(blob->GetBufferPointer(), 1, iter->second.blob_size, m_blob_file) != iter->second.blob_size)
|
||||
{
|
||||
Log_ErrorPrintf("Read blob from file failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3D11VertexShader> ShaderCache::GetVertexShader(ID3D11Device* device, std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Vertex, std::move(shader_code));
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return D3D11::ShaderCompiler::CreateVertexShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3D11GeometryShader> ShaderCache::GetGeometryShader(ID3D11Device* device,
|
||||
std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Geometry, std::move(shader_code));
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return D3D11::ShaderCompiler::CreateGeometryShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3D11PixelShader> ShaderCache::GetPixelShader(ID3D11Device* device, std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Pixel, std::move(shader_code));
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return D3D11::ShaderCompiler::CreatePixelShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3D11ComputeShader> ShaderCache::GetComputeShader(ID3D11Device* device,
|
||||
std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Compute, std::move(shader_code));
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return D3D11::ShaderCompiler::CreateComputeShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileAndAddShaderBlob(const CacheIndexKey& key,
|
||||
std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = ShaderCompiler::CompileShader(key.shader_type, m_feature_level, shader_code, m_debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
if (!m_blob_file || std::fseek(m_blob_file, 0, SEEK_END) != 0)
|
||||
return blob;
|
||||
|
||||
CacheIndexData data;
|
||||
data.file_offset = static_cast<u32>(std::ftell(m_blob_file));
|
||||
data.blob_size = static_cast<u32>(blob->GetBufferSize());
|
||||
|
||||
CacheIndexEntry entry = {};
|
||||
entry.source_hash_low = key.source_hash_low;
|
||||
entry.source_hash_high = key.source_hash_high;
|
||||
entry.source_length = key.source_length;
|
||||
entry.shader_type = static_cast<u32>(key.shader_type);
|
||||
entry.blob_size = data.blob_size;
|
||||
entry.file_offset = data.file_offset;
|
||||
|
||||
if (std::fwrite(blob->GetBufferPointer(), 1, entry.blob_size, m_blob_file) != entry.blob_size ||
|
||||
std::fflush(m_blob_file) != 0 || std::fwrite(&entry, sizeof(entry), 1, m_index_file) != 1 ||
|
||||
std::fflush(m_index_file) != 0)
|
||||
{
|
||||
Log_ErrorPrintf("Failed to write shader blob to file");
|
||||
return blob;
|
||||
}
|
||||
|
||||
m_index.emplace(key, data);
|
||||
return blob;
|
||||
}
|
||||
|
||||
} // namespace D3D11
|
|
@ -1,88 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/hash_combine.h"
|
||||
#include "common/types.h"
|
||||
#include "common/windows_headers.h"
|
||||
#include "shader_compiler.h"
|
||||
#include <cstdio>
|
||||
#include <d3d11.h>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <wrl/client.h>
|
||||
|
||||
namespace D3D11 {
|
||||
|
||||
class ShaderCache
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
ShaderCache();
|
||||
~ShaderCache();
|
||||
|
||||
void Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
|
||||
|
||||
ComPtr<ID3DBlob> GetShaderBlob(ShaderCompiler::Type type, std::string_view shader_code);
|
||||
|
||||
ComPtr<ID3D11VertexShader> GetVertexShader(ID3D11Device* device, std::string_view shader_code);
|
||||
ComPtr<ID3D11GeometryShader> GetGeometryShader(ID3D11Device* device, std::string_view shader_code);
|
||||
ComPtr<ID3D11PixelShader> GetPixelShader(ID3D11Device* device, std::string_view shader_code);
|
||||
ComPtr<ID3D11ComputeShader> GetComputeShader(ID3D11Device* device, std::string_view shader_code);
|
||||
|
||||
private:
|
||||
static constexpr u32 FILE_VERSION = 2;
|
||||
|
||||
struct CacheIndexKey
|
||||
{
|
||||
u64 source_hash_low;
|
||||
u64 source_hash_high;
|
||||
u32 source_length;
|
||||
ShaderCompiler::Type shader_type;
|
||||
|
||||
bool operator==(const CacheIndexKey& key) const;
|
||||
bool operator!=(const CacheIndexKey& key) const;
|
||||
};
|
||||
|
||||
struct CacheIndexEntryHasher
|
||||
{
|
||||
std::size_t operator()(const CacheIndexKey& e) const noexcept
|
||||
{
|
||||
std::size_t h = 0;
|
||||
hash_combine(h, e.source_hash_low, e.source_hash_high, e.source_length, e.shader_type);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct CacheIndexData
|
||||
{
|
||||
u32 file_offset;
|
||||
u32 blob_size;
|
||||
};
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static std::string GetCacheBaseFileName(const std::string_view& base_path, D3D_FEATURE_LEVEL feature_level,
|
||||
bool debug);
|
||||
static CacheIndexKey GetCacheKey(ShaderCompiler::Type type, const std::string_view& shader_code);
|
||||
|
||||
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
|
||||
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
|
||||
void Close();
|
||||
|
||||
ComPtr<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, std::string_view shader_code);
|
||||
|
||||
std::FILE* m_index_file = nullptr;
|
||||
std::FILE* m_blob_file = nullptr;
|
||||
|
||||
CacheIndex m_index;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
u32 m_version = 0;
|
||||
bool m_debug = false;
|
||||
};
|
||||
|
||||
} // namespace D3D11
|
|
@ -1,202 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "shader_compiler.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include <array>
|
||||
#include <d3dcompiler.h>
|
||||
#include <fstream>
|
||||
Log_SetChannel(D3D11);
|
||||
|
||||
namespace D3D11::ShaderCompiler {
|
||||
|
||||
static unsigned s_next_bad_shader_id = 1;
|
||||
|
||||
ComPtr<ID3DBlob> CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug)
|
||||
{
|
||||
const char* target;
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
default:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
|
||||
|
||||
ComPtr<ID3DBlob> blob;
|
||||
ComPtr<ID3DBlob> error_blob;
|
||||
const HRESULT hr =
|
||||
D3DCompile(code.data(), code.size(), "0", nullptr, nullptr, "main", target, debug ? flags_debug : flags_non_debug,
|
||||
0, blob.GetAddressOf(), error_blob.GetAddressOf());
|
||||
|
||||
std::string error_string;
|
||||
if (error_blob)
|
||||
{
|
||||
error_string.append(static_cast<const char*>(error_blob->GetBufferPointer()), error_blob->GetBufferSize());
|
||||
error_blob.Reset();
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to compile '%s':\n%s", target, error_string.c_str());
|
||||
|
||||
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
|
||||
std::ofstream::out | std::ofstream::binary);
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs << code;
|
||||
ofs << "\n\nCompile as " << target << " failed: " << hr << "\n";
|
||||
ofs.write(error_string.c_str(), error_string.size());
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!error_string.empty())
|
||||
Log_WarningPrintf("'%s' compiled with warnings:\n%s", target, error_string.c_str());
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, std::string_view code, bool debug)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = CompileShader(Type::Vertex, device->GetFeatureLevel(), std::move(code), debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateVertexShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, std::string_view code, bool debug)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = CompileShader(Type::Geometry, device->GetFeatureLevel(), std::move(code), debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateGeometryShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, std::string_view code, bool debug)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = CompileShader(Type::Pixel, device->GetFeatureLevel(), std::move(code), debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreatePixelShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, std::string_view code, bool debug)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob = CompileShader(Type::Compute, device->GetFeatureLevel(), std::move(code), debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
return CreateComputeShader(device, blob.Get());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
ComPtr<ID3D11VertexShader> shader;
|
||||
const HRESULT hr = device->CreateVertexShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create vertex shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateVertexShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
ComPtr<ID3D11GeometryShader> shader;
|
||||
const HRESULT hr = device->CreateGeometryShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create geometry shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateGeometryShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
ComPtr<ID3D11PixelShader> shader;
|
||||
const HRESULT hr = device->CreatePixelShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create pixel shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreatePixelShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
|
||||
{
|
||||
ComPtr<ID3D11ComputeShader> shader;
|
||||
const HRESULT hr = device->CreateComputeShader(bytecode, bytecode_length, nullptr, shader.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to create compute shader: 0x%08X", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob)
|
||||
{
|
||||
return CreateComputeShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
|
||||
const_cast<ID3DBlob*>(blob)->GetBufferSize());
|
||||
}
|
||||
|
||||
} // namespace D3D11::ShaderCompiler
|
|
@ -1,39 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/windows_headers.h"
|
||||
#include <d3d11.h>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <wrl/client.h>
|
||||
|
||||
namespace D3D11::ShaderCompiler {
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
enum class Type
|
||||
{
|
||||
Vertex,
|
||||
Geometry,
|
||||
Pixel,
|
||||
Compute
|
||||
};
|
||||
|
||||
ComPtr<ID3DBlob> CompileShader(Type type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug);
|
||||
|
||||
ComPtr<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, std::string_view code, bool debug);
|
||||
ComPtr<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, std::string_view code, bool debug);
|
||||
ComPtr<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, std::string_view code, bool debug);
|
||||
ComPtr<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, std::string_view code, bool debug);
|
||||
|
||||
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
ComPtr<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
ComPtr<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
ComPtr<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
|
||||
ComPtr<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const ID3DBlob* blob);
|
||||
|
||||
}; // namespace D3D11::ShaderCompiler
|
|
@ -1,113 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "stream_buffer.h"
|
||||
#include "common/align.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
Log_SetChannel(D3D11);
|
||||
|
||||
namespace D3D11 {
|
||||
|
||||
StreamBuffer::StreamBuffer() : m_size(0), m_position(0) {}
|
||||
|
||||
StreamBuffer::StreamBuffer(ComPtr<ID3D11Buffer> buffer) : m_buffer(std::move(buffer)), m_position(0)
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
m_buffer->GetDesc(&desc);
|
||||
m_size = desc.ByteWidth;
|
||||
}
|
||||
|
||||
StreamBuffer::~StreamBuffer()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
bool StreamBuffer::Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size)
|
||||
{
|
||||
CD3D11_BUFFER_DESC desc(size, bind_flags, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, 0, 0);
|
||||
ComPtr<ID3D11Buffer> buffer;
|
||||
HRESULT hr = device->CreateBuffer(&desc, nullptr, &buffer);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Creating buffer failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_buffer = std::move(buffer);
|
||||
m_size = size;
|
||||
m_position = 0;
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS options = {};
|
||||
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (bind_flags & D3D11_BIND_CONSTANT_BUFFER)
|
||||
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicConstantBuffer;
|
||||
else if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
|
||||
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicBufferSRV;
|
||||
else
|
||||
m_use_map_no_overwrite = true;
|
||||
|
||||
if (!m_use_map_no_overwrite)
|
||||
{
|
||||
Log_WarningPrintf("Unable to use MAP_NO_OVERWRITE on buffer with bind flag %u, this may affect performance. "
|
||||
"Update your driver/operating system.",
|
||||
static_cast<unsigned>(bind_flags));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_WarningPrintf("ID3D11Device::CheckFeatureSupport() failed: 0x%08X", hr);
|
||||
m_use_map_no_overwrite = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StreamBuffer::Adopt(ComPtr<ID3D11Buffer> buffer)
|
||||
{
|
||||
m_buffer = std::move(buffer);
|
||||
|
||||
D3D11_BUFFER_DESC desc;
|
||||
m_buffer->GetDesc(&desc);
|
||||
m_size = desc.ByteWidth;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
void StreamBuffer::Release()
|
||||
{
|
||||
m_buffer.Reset();
|
||||
}
|
||||
|
||||
StreamBuffer::MappingResult StreamBuffer::Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size)
|
||||
{
|
||||
m_position = Common::AlignUp(m_position, alignment);
|
||||
if ((m_position + min_size) >= m_size || !m_use_map_no_overwrite)
|
||||
{
|
||||
// wrap around
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
const D3D11_MAP map_type = (m_position == 0) ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
const HRESULT hr = context->Map(m_buffer.Get(), 0, map_type, 0, &sr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Map failed: 0x%08X (alignment %u, minsize %u, size %u, position %u, map type %u)", hr, alignment,
|
||||
min_size, m_size, m_position, static_cast<u32>(map_type));
|
||||
Panic("Map failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
return MappingResult{static_cast<char*>(sr.pData) + m_position, m_position, m_position / alignment,
|
||||
(m_size - m_position) / alignment};
|
||||
}
|
||||
|
||||
void StreamBuffer::Unmap(ID3D11DeviceContext* context, u32 used_size)
|
||||
{
|
||||
context->Unmap(m_buffer.Get(), 0);
|
||||
m_position += used_size;
|
||||
}
|
||||
|
||||
} // namespace D3D11
|
|
@ -1,47 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/types.h"
|
||||
#include "common/windows_headers.h"
|
||||
#include <d3d11.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
namespace D3D11 {
|
||||
class StreamBuffer
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
StreamBuffer();
|
||||
StreamBuffer(ComPtr<ID3D11Buffer> buffer);
|
||||
~StreamBuffer();
|
||||
|
||||
ALWAYS_INLINE ID3D11Buffer* GetD3DBuffer() const { return m_buffer.Get(); }
|
||||
ALWAYS_INLINE ID3D11Buffer* const* GetD3DBufferArray() const { return m_buffer.GetAddressOf(); }
|
||||
ALWAYS_INLINE u32 GetSize() const { return m_size; }
|
||||
ALWAYS_INLINE u32 GetPosition() const { return m_position; }
|
||||
|
||||
bool Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size);
|
||||
void Adopt(ComPtr<ID3D11Buffer> buffer);
|
||||
void Release();
|
||||
|
||||
struct MappingResult
|
||||
{
|
||||
void* pointer;
|
||||
u32 buffer_offset;
|
||||
u32 index_aligned; // offset / alignment, suitable for base vertex
|
||||
u32 space_aligned; // remaining space / alignment
|
||||
};
|
||||
|
||||
MappingResult Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size);
|
||||
void Unmap(ID3D11DeviceContext* context, u32 used_size);
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Buffer> m_buffer;
|
||||
u32 m_size;
|
||||
u32 m_position;
|
||||
bool m_use_map_no_overwrite = false;
|
||||
};
|
||||
} // namespace D3D11
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d11_device.h"
|
||||
|
@ -7,6 +7,7 @@
|
|||
#include "../shader_cache_version.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/align.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
|
@ -25,7 +26,12 @@ Log_SetChannel(D3D11Device);
|
|||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
|
||||
static constexpr std::array<DXGI_FORMAT, static_cast<u32>(GPUTexture::Format::Count)> s_dxgi_mapping = {
|
||||
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B5G6R5_UNORM,
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_D16_UNORM}};
|
||||
|
||||
static constexpr std::array<float, 4> s_clear_color = {};
|
||||
|
||||
static unsigned s_next_bad_shader_id = 1;
|
||||
|
||||
static void SetD3DDebugObjectName(ID3D11DeviceChild* obj, const std::string_view& name)
|
||||
|
@ -36,6 +42,109 @@ static void SetD3DDebugObjectName(ID3D11DeviceChild* obj, const std::string_view
|
|||
obj->SetPrivateData(guid, static_cast<UINT>(wname.length()) * 2u, wname.c_str());
|
||||
}
|
||||
|
||||
D3D11StreamBuffer::D3D11StreamBuffer() : m_size(0), m_position(0)
|
||||
{
|
||||
}
|
||||
|
||||
D3D11StreamBuffer::D3D11StreamBuffer(ComPtr<ID3D11Buffer> buffer) : m_buffer(std::move(buffer)), m_position(0)
|
||||
{
|
||||
D3D11_BUFFER_DESC desc;
|
||||
m_buffer->GetDesc(&desc);
|
||||
m_size = desc.ByteWidth;
|
||||
}
|
||||
|
||||
D3D11StreamBuffer::~D3D11StreamBuffer()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
bool D3D11StreamBuffer::Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size)
|
||||
{
|
||||
CD3D11_BUFFER_DESC desc(size, bind_flags, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, 0, 0);
|
||||
ComPtr<ID3D11Buffer> buffer;
|
||||
HRESULT hr = device->CreateBuffer(&desc, nullptr, &buffer);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Creating buffer failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_buffer = std::move(buffer);
|
||||
m_size = size;
|
||||
m_position = 0;
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS options = {};
|
||||
hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (bind_flags & D3D11_BIND_CONSTANT_BUFFER)
|
||||
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicConstantBuffer;
|
||||
else if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
|
||||
m_use_map_no_overwrite = options.MapNoOverwriteOnDynamicBufferSRV;
|
||||
else
|
||||
m_use_map_no_overwrite = true;
|
||||
|
||||
if (!m_use_map_no_overwrite)
|
||||
{
|
||||
Log_WarningPrintf("Unable to use MAP_NO_OVERWRITE on buffer with bind flag %u, this may affect performance. "
|
||||
"Update your driver/operating system.",
|
||||
static_cast<unsigned>(bind_flags));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_WarningPrintf("ID3D11Device::CheckFeatureSupport() failed: 0x%08X", hr);
|
||||
m_use_map_no_overwrite = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11StreamBuffer::Adopt(ComPtr<ID3D11Buffer> buffer)
|
||||
{
|
||||
m_buffer = std::move(buffer);
|
||||
|
||||
D3D11_BUFFER_DESC desc;
|
||||
m_buffer->GetDesc(&desc);
|
||||
m_size = desc.ByteWidth;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
void D3D11StreamBuffer::Release()
|
||||
{
|
||||
m_buffer.Reset();
|
||||
}
|
||||
|
||||
D3D11StreamBuffer::MappingResult D3D11StreamBuffer::Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size)
|
||||
{
|
||||
m_position = Common::AlignUp(m_position, alignment);
|
||||
if ((m_position + min_size) >= m_size || !m_use_map_no_overwrite)
|
||||
{
|
||||
// wrap around
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
const D3D11_MAP map_type = (m_position == 0) ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE;
|
||||
const HRESULT hr = context->Map(m_buffer.Get(), 0, map_type, 0, &sr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Map failed: 0x%08X (alignment %u, minsize %u, size %u, position %u, map type %u)", hr, alignment,
|
||||
min_size, m_size, m_position, static_cast<u32>(map_type));
|
||||
Panic("Map failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
return MappingResult{static_cast<char*>(sr.pData) + m_position, m_position, m_position / alignment,
|
||||
(m_size - m_position) / alignment};
|
||||
}
|
||||
|
||||
void D3D11StreamBuffer::Unmap(ID3D11DeviceContext* context, u32 used_size)
|
||||
{
|
||||
context->Unmap(m_buffer.Get(), 0);
|
||||
m_position += used_size;
|
||||
}
|
||||
|
||||
D3D11Device::D3D11Device() = default;
|
||||
|
||||
D3D11Device::~D3D11Device()
|
||||
|
@ -679,7 +788,7 @@ bool D3D11Device::Render(bool skip_present)
|
|||
|
||||
if (m_gpu_timing_enabled)
|
||||
KickTimestampQuery();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1487,6 +1596,321 @@ std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::Grap
|
|||
primitives[static_cast<u8>(config.primitive)]));
|
||||
}
|
||||
|
||||
D3D11Texture::D3D11Texture() = default;
|
||||
|
||||
D3D11Texture::D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv,
|
||||
ComPtr<ID3D11View> rtv)
|
||||
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_rtv_dsv(std::move(rtv))
|
||||
{
|
||||
const D3D11_TEXTURE2D_DESC desc = GetDesc();
|
||||
m_width = static_cast<u16>(desc.Width);
|
||||
m_height = static_cast<u16>(desc.Height);
|
||||
m_layers = static_cast<u8>(desc.ArraySize);
|
||||
m_levels = static_cast<u8>(desc.MipLevels);
|
||||
m_samples = static_cast<u8>(desc.SampleDesc.Count);
|
||||
m_format = LookupBaseFormat(desc.Format);
|
||||
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
|
||||
}
|
||||
|
||||
D3D11Texture::~D3D11Texture()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
DXGI_FORMAT D3D11Texture::GetDXGIFormat(Format format)
|
||||
{
|
||||
return s_dxgi_mapping[static_cast<u8>(format)];
|
||||
}
|
||||
|
||||
GPUTexture::Format D3D11Texture::LookupBaseFormat(DXGI_FORMAT dformat)
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(s_dxgi_mapping.size()); i++)
|
||||
{
|
||||
if (s_dxgi_mapping[i] == dformat)
|
||||
return static_cast<Format>(i);
|
||||
}
|
||||
return GPUTexture::Format::Unknown;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
m_texture->GetDesc(&desc);
|
||||
return desc;
|
||||
}
|
||||
|
||||
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
|
||||
{
|
||||
if (m_state == GPUTexture::State::Dirty)
|
||||
return;
|
||||
|
||||
// TODO: 11.1
|
||||
if (IsDepthStencil())
|
||||
{
|
||||
if (m_state == GPUTexture::State::Invalidated)
|
||||
; // context->DiscardView(GetD3DDSV());
|
||||
else
|
||||
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
|
||||
}
|
||||
else if (IsRenderTarget())
|
||||
{
|
||||
if (m_state == GPUTexture::State::Invalidated)
|
||||
; // context->DiscardView(GetD3DRTV());
|
||||
else
|
||||
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
|
||||
}
|
||||
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
}
|
||||
|
||||
bool D3D11Texture::IsValid() const
|
||||
{
|
||||
return static_cast<bool>(m_texture);
|
||||
}
|
||||
|
||||
bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer /*= 0*/,
|
||||
u32 level /*= 0*/)
|
||||
{
|
||||
if (m_dynamic)
|
||||
{
|
||||
void* map;
|
||||
u32 map_stride;
|
||||
if (!Map(&map, &map_stride, x, y, width, height, layer, level))
|
||||
return false;
|
||||
|
||||
StringUtil::StrideMemCpy(map, map_stride, data, pitch, GetPixelSize() * width, height);
|
||||
Unmap();
|
||||
return true;
|
||||
}
|
||||
|
||||
const CD3D11_BOX box(static_cast<LONG>(x), static_cast<LONG>(y), 0, static_cast<LONG>(x + width),
|
||||
static_cast<LONG>(y + height), 1);
|
||||
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
|
||||
|
||||
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
|
||||
CommitClear(context);
|
||||
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer /*= 0*/,
|
||||
u32 level /*= 0*/)
|
||||
{
|
||||
if (!m_dynamic || (x + width) > m_width || (y + height) > m_height || layer > m_layers || level > m_levels)
|
||||
return false;
|
||||
|
||||
const bool discard = (width == m_width && height == m_height);
|
||||
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
|
||||
|
||||
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
|
||||
CommitClear(context);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
|
||||
*map_stride = sr.RowPitch;
|
||||
m_mapped_subresource = srnum;
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11Texture::Unmap()
|
||||
{
|
||||
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), m_mapped_subresource);
|
||||
m_mapped_subresource = 0;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
|
||||
Format format, const void* initial_data /* = nullptr */, u32 initial_data_stride /* = 0 */,
|
||||
bool dynamic /* = false */)
|
||||
{
|
||||
if (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ||
|
||||
layers > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION || (layers > 1 && samples > 1))
|
||||
{
|
||||
Log_ErrorPrintf("Texture bounds (%ux%ux%u, %u mips, %u samples) are too large", width, height, layers, levels,
|
||||
samples);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 bind_flags = 0;
|
||||
switch (type)
|
||||
{
|
||||
case Type::RenderTarget:
|
||||
bind_flags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::DepthStencil:
|
||||
bind_flags = D3D11_BIND_DEPTH_STENCIL; // | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::Texture:
|
||||
bind_flags = D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::RWTexture:
|
||||
bind_flags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormat(format), width, height, layers, levels, bind_flags,
|
||||
dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, dynamic ? D3D11_CPU_ACCESS_WRITE : 0,
|
||||
samples, 0, 0);
|
||||
|
||||
D3D11_SUBRESOURCE_DATA srd;
|
||||
srd.pSysMem = initial_data;
|
||||
srd.SysMemPitch = initial_data_stride;
|
||||
srd.SysMemSlicePitch = initial_data_stride * height;
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
const HRESULT tex_hr = device->CreateTexture2D(&desc, initial_data ? &srd : nullptr, texture.GetAddressOf());
|
||||
if (FAILED(tex_hr))
|
||||
{
|
||||
Log_ErrorPrintf(
|
||||
"Create texture failed: 0x%08X (%ux%u levels:%u samples:%u format:%u bind_flags:%X initial_data:%p)", tex_hr,
|
||||
width, height, levels, samples, static_cast<unsigned>(format), bind_flags, initial_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> srv;
|
||||
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
|
||||
{
|
||||
const D3D11_SRV_DIMENSION srv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ?
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DMS :
|
||||
(desc.ArraySize > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D);
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
|
||||
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create SRV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ComPtr<ID3D11View> rtv_dsv;
|
||||
if (bind_flags & D3D11_BIND_RENDER_TARGET)
|
||||
{
|
||||
const D3D11_RTV_DIMENSION rtv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create RTV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(rtv);
|
||||
}
|
||||
else if (bind_flags & D3D11_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
const D3D11_DSV_DIMENSION dsv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create DSV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(dsv);
|
||||
}
|
||||
|
||||
m_texture = std::move(texture);
|
||||
m_srv = std::move(srv);
|
||||
m_rtv_dsv = std::move(rtv_dsv);
|
||||
m_width = static_cast<u16>(width);
|
||||
m_height = static_cast<u16>(height);
|
||||
m_layers = static_cast<u8>(layers);
|
||||
m_levels = static_cast<u8>(levels);
|
||||
m_samples = static_cast<u8>(samples);
|
||||
m_format = format;
|
||||
m_dynamic = dynamic;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> srv;
|
||||
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
|
||||
{
|
||||
const D3D11_SRV_DIMENSION srv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
|
||||
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create SRV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ComPtr<ID3D11View> rtv_dsv;
|
||||
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
|
||||
{
|
||||
const D3D11_RTV_DIMENSION rtv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create RTV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(rtv);
|
||||
}
|
||||
else if (desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
const D3D11_DSV_DIMENSION dsv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create DSV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(dsv);
|
||||
}
|
||||
|
||||
m_texture = std::move(texture);
|
||||
m_srv = std::move(srv);
|
||||
m_rtv_dsv = std::move(rtv_dsv);
|
||||
m_width = static_cast<u16>(desc.Width);
|
||||
m_height = static_cast<u16>(desc.Height);
|
||||
m_layers = static_cast<u8>(desc.ArraySize);
|
||||
m_levels = static_cast<u8>(desc.MipLevels);
|
||||
m_samples = static_cast<u8>(desc.SampleDesc.Count);
|
||||
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11Texture::Destroy()
|
||||
{
|
||||
m_rtv_dsv.Reset();
|
||||
m_srv.Reset();
|
||||
m_texture.Reset();
|
||||
m_dynamic = false;
|
||||
ClearBaseProperties();
|
||||
}
|
||||
|
||||
void D3D11Device::PushDebugGroup(const char* fmt, ...)
|
||||
{
|
||||
if (!m_annotation)
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include "common/timer.h"
|
||||
#include "common/window_info.h"
|
||||
#include "common/windows_headers.h"
|
||||
#include "d3d11/stream_buffer.h"
|
||||
#include "d3d11_texture.h"
|
||||
#include "gpu_device.h"
|
||||
#include "postprocessing_chain.h"
|
||||
#include <d3d11_1.h>
|
||||
|
@ -21,6 +19,43 @@
|
|||
|
||||
class D3D11Device;
|
||||
|
||||
class D3D11StreamBuffer
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
D3D11StreamBuffer();
|
||||
D3D11StreamBuffer(ComPtr<ID3D11Buffer> buffer);
|
||||
~D3D11StreamBuffer();
|
||||
|
||||
ALWAYS_INLINE ID3D11Buffer* GetD3DBuffer() const { return m_buffer.Get(); }
|
||||
ALWAYS_INLINE ID3D11Buffer* const* GetD3DBufferArray() const { return m_buffer.GetAddressOf(); }
|
||||
ALWAYS_INLINE u32 GetSize() const { return m_size; }
|
||||
ALWAYS_INLINE u32 GetPosition() const { return m_position; }
|
||||
|
||||
bool Create(ID3D11Device* device, D3D11_BIND_FLAG bind_flags, u32 size);
|
||||
void Adopt(ComPtr<ID3D11Buffer> buffer);
|
||||
void Release();
|
||||
|
||||
struct MappingResult
|
||||
{
|
||||
void* pointer;
|
||||
u32 buffer_offset;
|
||||
u32 index_aligned; // offset / alignment, suitable for base vertex
|
||||
u32 space_aligned; // remaining space / alignment
|
||||
};
|
||||
|
||||
MappingResult Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size);
|
||||
void Unmap(ID3D11DeviceContext* context, u32 used_size);
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Buffer> m_buffer;
|
||||
u32 m_size;
|
||||
u32 m_position;
|
||||
bool m_use_map_no_overwrite = false;
|
||||
};
|
||||
|
||||
class D3D11Framebuffer final : public GPUFramebuffer
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
@ -126,6 +161,74 @@ private:
|
|||
D3D11_PRIMITIVE_TOPOLOGY m_topology;
|
||||
};
|
||||
|
||||
class D3D11Texture final : public GPUTexture
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
D3D11Texture();
|
||||
D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, ComPtr<ID3D11View> rtv);
|
||||
~D3D11Texture();
|
||||
|
||||
static DXGI_FORMAT GetDXGIFormat(Format format);
|
||||
static Format LookupBaseFormat(DXGI_FORMAT dformat);
|
||||
|
||||
ALWAYS_INLINE ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); }
|
||||
ALWAYS_INLINE ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
|
||||
ALWAYS_INLINE ID3D11RenderTargetView* GetD3DRTV() const
|
||||
{
|
||||
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE ID3D11DepthStencilView* GetD3DDSV() const
|
||||
{
|
||||
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE ID3D11ShaderResourceView* const* GetD3DSRVArray() const { return m_srv.GetAddressOf(); }
|
||||
ALWAYS_INLINE ID3D11RenderTargetView* const* GetD3DRTVArray() const
|
||||
{
|
||||
return reinterpret_cast<ID3D11RenderTargetView* const*>(m_rtv_dsv.GetAddressOf());
|
||||
}
|
||||
ALWAYS_INLINE DXGI_FORMAT GetDXGIFormat() const { return GetDXGIFormat(m_format); }
|
||||
ALWAYS_INLINE bool IsDynamic() const { return m_dynamic; }
|
||||
|
||||
ALWAYS_INLINE operator ID3D11Texture2D*() const { return m_texture.Get(); }
|
||||
ALWAYS_INLINE operator ID3D11ShaderResourceView*() const { return m_srv.Get(); }
|
||||
ALWAYS_INLINE operator ID3D11RenderTargetView*() const
|
||||
{
|
||||
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE operator ID3D11DepthStencilView*() const
|
||||
{
|
||||
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE operator bool() const { return static_cast<bool>(m_texture); }
|
||||
|
||||
bool Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
|
||||
Format format, const void* initial_data = nullptr, u32 initial_data_stride = 0, bool dynamic = false);
|
||||
bool Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture);
|
||||
|
||||
void Destroy();
|
||||
|
||||
D3D11_TEXTURE2D_DESC GetDesc() const;
|
||||
void CommitClear(ID3D11DeviceContext* context);
|
||||
|
||||
bool IsValid() const override;
|
||||
|
||||
bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override;
|
||||
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
|
||||
void Unmap() override;
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Texture2D> m_texture;
|
||||
ComPtr<ID3D11ShaderResourceView> m_srv;
|
||||
ComPtr<ID3D11View> m_rtv_dsv;
|
||||
u32 m_mapped_subresource = 0;
|
||||
bool m_dynamic = false;
|
||||
};
|
||||
|
||||
class D3D11Device final : public GPUDevice
|
||||
{
|
||||
public:
|
||||
|
@ -278,9 +381,9 @@ private:
|
|||
bool m_using_flip_model_swap_chain = true;
|
||||
bool m_using_allow_tearing = false;
|
||||
|
||||
D3D11::StreamBuffer m_vertex_buffer;
|
||||
D3D11::StreamBuffer m_index_buffer;
|
||||
D3D11::StreamBuffer m_uniform_buffer;
|
||||
D3D11StreamBuffer m_vertex_buffer;
|
||||
D3D11StreamBuffer m_index_buffer;
|
||||
D3D11StreamBuffer m_uniform_buffer;
|
||||
|
||||
D3D11Framebuffer* m_current_framebuffer = nullptr;
|
||||
D3D11Pipeline* m_current_pipeline = nullptr;
|
||||
|
|
|
@ -1,329 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "d3d11_texture.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "d3d11_device.h"
|
||||
#include <array>
|
||||
Log_SetChannel(D3D11);
|
||||
|
||||
static constexpr std::array<DXGI_FORMAT, static_cast<u32>(GPUTexture::Format::Count)> s_dxgi_mapping = {
|
||||
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B5G6R5_UNORM,
|
||||
DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_D16_UNORM}};
|
||||
|
||||
D3D11Texture::D3D11Texture() = default;
|
||||
|
||||
D3D11Texture::D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv,
|
||||
ComPtr<ID3D11View> rtv)
|
||||
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_rtv_dsv(std::move(rtv))
|
||||
{
|
||||
const D3D11_TEXTURE2D_DESC desc = GetDesc();
|
||||
m_width = static_cast<u16>(desc.Width);
|
||||
m_height = static_cast<u16>(desc.Height);
|
||||
m_layers = static_cast<u8>(desc.ArraySize);
|
||||
m_levels = static_cast<u8>(desc.MipLevels);
|
||||
m_samples = static_cast<u8>(desc.SampleDesc.Count);
|
||||
m_format = LookupBaseFormat(desc.Format);
|
||||
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
|
||||
}
|
||||
|
||||
D3D11Texture::~D3D11Texture()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
DXGI_FORMAT D3D11Texture::GetDXGIFormat(Format format)
|
||||
{
|
||||
return s_dxgi_mapping[static_cast<u8>(format)];
|
||||
}
|
||||
|
||||
GPUTexture::Format D3D11Texture::LookupBaseFormat(DXGI_FORMAT dformat)
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(s_dxgi_mapping.size()); i++)
|
||||
{
|
||||
if (s_dxgi_mapping[i] == dformat)
|
||||
return static_cast<Format>(i);
|
||||
}
|
||||
return GPUTexture::Format::Unknown;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
m_texture->GetDesc(&desc);
|
||||
return desc;
|
||||
}
|
||||
|
||||
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
|
||||
{
|
||||
if (m_state == GPUTexture::State::Dirty)
|
||||
return;
|
||||
|
||||
// TODO: 11.1
|
||||
if (IsDepthStencil())
|
||||
{
|
||||
if (m_state == GPUTexture::State::Invalidated)
|
||||
; // context->DiscardView(GetD3DDSV());
|
||||
else
|
||||
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
|
||||
}
|
||||
else if (IsRenderTarget())
|
||||
{
|
||||
if (m_state == GPUTexture::State::Invalidated)
|
||||
; // context->DiscardView(GetD3DRTV());
|
||||
else
|
||||
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
|
||||
}
|
||||
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
}
|
||||
|
||||
bool D3D11Texture::IsValid() const
|
||||
{
|
||||
return static_cast<bool>(m_texture);
|
||||
}
|
||||
|
||||
bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer /*= 0*/,
|
||||
u32 level /*= 0*/)
|
||||
{
|
||||
if (m_dynamic)
|
||||
{
|
||||
void* map;
|
||||
u32 map_stride;
|
||||
if (!Map(&map, &map_stride, x, y, width, height, layer, level))
|
||||
return false;
|
||||
|
||||
StringUtil::StrideMemCpy(map, map_stride, data, pitch, GetPixelSize() * width, height);
|
||||
Unmap();
|
||||
return true;
|
||||
}
|
||||
|
||||
const CD3D11_BOX box(static_cast<LONG>(x), static_cast<LONG>(y), 0, static_cast<LONG>(x + width),
|
||||
static_cast<LONG>(y + height), 1);
|
||||
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
|
||||
|
||||
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
|
||||
CommitClear(context);
|
||||
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer /*= 0*/,
|
||||
u32 level /*= 0*/)
|
||||
{
|
||||
if (!m_dynamic || (x + width) > m_width || (y + height) > m_height || layer > m_layers || level > m_levels)
|
||||
return false;
|
||||
|
||||
const bool discard = (width == m_width && height == m_height);
|
||||
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
|
||||
|
||||
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
|
||||
CommitClear(context);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE sr;
|
||||
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
|
||||
*map_stride = sr.RowPitch;
|
||||
m_mapped_subresource = srnum;
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11Texture::Unmap()
|
||||
{
|
||||
D3D11Device::GetD3DContext()->Unmap(m_texture.Get(), m_mapped_subresource);
|
||||
m_mapped_subresource = 0;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
|
||||
Format format, const void* initial_data /* = nullptr */, u32 initial_data_stride /* = 0 */,
|
||||
bool dynamic /* = false */)
|
||||
{
|
||||
if (width > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION || height > D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION ||
|
||||
layers > D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION || (layers > 1 && samples > 1))
|
||||
{
|
||||
Log_ErrorPrintf("Texture bounds (%ux%ux%u, %u mips, %u samples) are too large", width, height, layers, levels,
|
||||
samples);
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 bind_flags = 0;
|
||||
switch (type)
|
||||
{
|
||||
case Type::RenderTarget:
|
||||
bind_flags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::DepthStencil:
|
||||
bind_flags = D3D11_BIND_DEPTH_STENCIL; // | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::Texture:
|
||||
bind_flags = D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
case Type::RWTexture:
|
||||
bind_flags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC desc(GetDXGIFormat(format), width, height, layers, levels, bind_flags,
|
||||
dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, dynamic ? D3D11_CPU_ACCESS_WRITE : 0,
|
||||
samples, 0, 0);
|
||||
|
||||
D3D11_SUBRESOURCE_DATA srd;
|
||||
srd.pSysMem = initial_data;
|
||||
srd.SysMemPitch = initial_data_stride;
|
||||
srd.SysMemSlicePitch = initial_data_stride * height;
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture;
|
||||
const HRESULT tex_hr = device->CreateTexture2D(&desc, initial_data ? &srd : nullptr, texture.GetAddressOf());
|
||||
if (FAILED(tex_hr))
|
||||
{
|
||||
Log_ErrorPrintf(
|
||||
"Create texture failed: 0x%08X (%ux%u levels:%u samples:%u format:%u bind_flags:%X initial_data:%p)", tex_hr,
|
||||
width, height, levels, samples, static_cast<unsigned>(format), bind_flags, initial_data);
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> srv;
|
||||
if (bind_flags & D3D11_BIND_SHADER_RESOURCE)
|
||||
{
|
||||
const D3D11_SRV_DIMENSION srv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ?
|
||||
D3D11_SRV_DIMENSION_TEXTURE2DMS :
|
||||
(desc.ArraySize > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D);
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
|
||||
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create SRV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ComPtr<ID3D11View> rtv_dsv;
|
||||
if (bind_flags & D3D11_BIND_RENDER_TARGET)
|
||||
{
|
||||
const D3D11_RTV_DIMENSION rtv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create RTV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(rtv);
|
||||
}
|
||||
else if (bind_flags & D3D11_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
const D3D11_DSV_DIMENSION dsv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create DSV for texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(dsv);
|
||||
}
|
||||
|
||||
m_texture = std::move(texture);
|
||||
m_srv = std::move(srv);
|
||||
m_rtv_dsv = std::move(rtv_dsv);
|
||||
m_width = static_cast<u16>(width);
|
||||
m_height = static_cast<u16>(height);
|
||||
m_layers = static_cast<u8>(layers);
|
||||
m_levels = static_cast<u8>(levels);
|
||||
m_samples = static_cast<u8>(samples);
|
||||
m_format = format;
|
||||
m_dynamic = dynamic;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> srv;
|
||||
if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
|
||||
{
|
||||
const D3D11_SRV_DIMENSION srv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(srv_dimension, desc.Format, 0, desc.MipLevels, 0, desc.ArraySize);
|
||||
const HRESULT hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create SRV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ComPtr<ID3D11View> rtv_dsv;
|
||||
if (desc.BindFlags & D3D11_BIND_RENDER_TARGET)
|
||||
{
|
||||
const D3D11_RTV_DIMENSION rtv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(rtv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
const HRESULT hr = device->CreateRenderTargetView(texture.Get(), &rtv_desc, rtv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create RTV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(rtv);
|
||||
}
|
||||
else if (desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
|
||||
{
|
||||
const D3D11_DSV_DIMENSION dsv_dimension =
|
||||
(desc.SampleDesc.Count > 1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
const CD3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc(dsv_dimension, desc.Format, 0, 0, desc.ArraySize);
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
const HRESULT hr = device->CreateDepthStencilView(texture.Get(), &dsv_desc, dsv.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Create DSV for adopted texture failed: 0x%08X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
rtv_dsv = std::move(dsv);
|
||||
}
|
||||
|
||||
m_texture = std::move(texture);
|
||||
m_srv = std::move(srv);
|
||||
m_rtv_dsv = std::move(rtv_dsv);
|
||||
m_width = static_cast<u16>(desc.Width);
|
||||
m_height = static_cast<u16>(desc.Height);
|
||||
m_layers = static_cast<u8>(desc.ArraySize);
|
||||
m_levels = static_cast<u8>(desc.MipLevels);
|
||||
m_samples = static_cast<u8>(desc.SampleDesc.Count);
|
||||
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
|
||||
m_state = GPUTexture::State::Dirty;
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11Texture::Destroy()
|
||||
{
|
||||
m_rtv_dsv.Reset();
|
||||
m_srv.Reset();
|
||||
m_texture.Reset();
|
||||
m_dynamic = false;
|
||||
ClearBaseProperties();
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/windows_headers.h"
|
||||
#include "gpu_texture.h"
|
||||
#include <d3d11.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class D3D11Device;
|
||||
|
||||
class D3D11Texture final : public GPUTexture
|
||||
{
|
||||
friend D3D11Device;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
D3D11Texture();
|
||||
D3D11Texture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, ComPtr<ID3D11View> rtv);
|
||||
~D3D11Texture();
|
||||
|
||||
static DXGI_FORMAT GetDXGIFormat(Format format);
|
||||
static Format LookupBaseFormat(DXGI_FORMAT dformat);
|
||||
|
||||
ALWAYS_INLINE ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); }
|
||||
ALWAYS_INLINE ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
|
||||
ALWAYS_INLINE ID3D11RenderTargetView* GetD3DRTV() const
|
||||
{
|
||||
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE ID3D11DepthStencilView* GetD3DDSV() const
|
||||
{
|
||||
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE ID3D11ShaderResourceView* const* GetD3DSRVArray() const { return m_srv.GetAddressOf(); }
|
||||
ALWAYS_INLINE ID3D11RenderTargetView* const* GetD3DRTVArray() const
|
||||
{
|
||||
return reinterpret_cast<ID3D11RenderTargetView* const*>(m_rtv_dsv.GetAddressOf());
|
||||
}
|
||||
ALWAYS_INLINE DXGI_FORMAT GetDXGIFormat() const { return GetDXGIFormat(m_format); }
|
||||
ALWAYS_INLINE bool IsDynamic() const { return m_dynamic; }
|
||||
|
||||
ALWAYS_INLINE operator ID3D11Texture2D*() const { return m_texture.Get(); }
|
||||
ALWAYS_INLINE operator ID3D11ShaderResourceView*() const { return m_srv.Get(); }
|
||||
ALWAYS_INLINE operator ID3D11RenderTargetView*() const
|
||||
{
|
||||
return static_cast<ID3D11RenderTargetView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE operator ID3D11DepthStencilView*() const
|
||||
{
|
||||
return static_cast<ID3D11DepthStencilView*>(m_rtv_dsv.Get());
|
||||
}
|
||||
ALWAYS_INLINE operator bool() const { return static_cast<bool>(m_texture); }
|
||||
|
||||
bool Create(ID3D11Device* device, u32 width, u32 height, u32 layers, u32 levels, u32 samples, Type type,
|
||||
Format format, const void* initial_data = nullptr, u32 initial_data_stride = 0, bool dynamic = false);
|
||||
bool Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture);
|
||||
|
||||
void Destroy();
|
||||
|
||||
D3D11_TEXTURE2D_DESC GetDesc() const;
|
||||
void CommitClear(ID3D11DeviceContext* context);
|
||||
|
||||
bool IsValid() const override;
|
||||
|
||||
bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch, u32 layer = 0, u32 level = 0) override;
|
||||
bool Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32 height, u32 layer = 0, u32 level = 0) override;
|
||||
void Unmap() override;
|
||||
|
||||
private:
|
||||
ComPtr<ID3D11Texture2D> m_texture;
|
||||
ComPtr<ID3D11ShaderResourceView> m_srv;
|
||||
ComPtr<ID3D11View> m_rtv_dsv;
|
||||
u32 m_mapped_subresource = 0;
|
||||
bool m_dynamic = false;
|
||||
};
|
|
@ -2,11 +2,13 @@
|
|||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "shader_cache.h"
|
||||
#include "../d3d11/shader_compiler.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/log.h"
|
||||
#include "common/md5_digest.h"
|
||||
#include "common/string_util.h"
|
||||
#include <array>
|
||||
#include <d3dcompiler.h>
|
||||
#include <fstream>
|
||||
Log_SetChannel(D3D12::ShaderCache);
|
||||
|
||||
namespace D3D12 {
|
||||
|
@ -358,29 +360,86 @@ ShaderCache::ComPtr<ID3D12PipelineState> ShaderCache::GetPipelineState(ID3D12Dev
|
|||
return pso;
|
||||
}
|
||||
|
||||
static unsigned s_next_bad_shader_id = 1;
|
||||
|
||||
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileShader(EntryType type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug)
|
||||
{
|
||||
const char* target;
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
default:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
|
||||
|
||||
ComPtr<ID3DBlob> blob;
|
||||
ComPtr<ID3DBlob> error_blob;
|
||||
const HRESULT hr =
|
||||
D3DCompile(code.data(), code.size(), "0", nullptr, nullptr, "main", target, debug ? flags_debug : flags_non_debug,
|
||||
0, blob.GetAddressOf(), error_blob.GetAddressOf());
|
||||
|
||||
std::string error_string;
|
||||
if (error_blob)
|
||||
{
|
||||
error_string.append(static_cast<const char*>(error_blob->GetBufferPointer()), error_blob->GetBufferSize());
|
||||
error_blob.Reset();
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Log_ErrorPrintf("Failed to compile '%s':\n%s", target, error_string.c_str());
|
||||
|
||||
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
|
||||
std::ofstream::out | std::ofstream::binary);
|
||||
if (ofs.is_open())
|
||||
{
|
||||
ofs << code;
|
||||
ofs << "\n\nCompile as " << target << " failed: " << hr << "\n";
|
||||
ofs.write(error_string.c_str(), error_string.size());
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!error_string.empty())
|
||||
Log_WarningPrintf("'%s' compiled with warnings:\n%s", target, error_string.c_str());
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileAndAddShaderBlob(const CacheIndexKey& key,
|
||||
std::string_view shader_code)
|
||||
{
|
||||
ComPtr<ID3DBlob> blob;
|
||||
|
||||
switch (key.type)
|
||||
{
|
||||
case EntryType::VertexShader:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_feature_level, shader_code,
|
||||
m_debug);
|
||||
break;
|
||||
case EntryType::GeometryShader:
|
||||
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Geometry, m_feature_level, shader_code,
|
||||
m_debug);
|
||||
break;
|
||||
case EntryType::PixelShader:
|
||||
blob =
|
||||
D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_feature_level, shader_code, m_debug);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ComPtr<ID3DBlob> blob = CompileShader(key.type, m_feature_level, shader_code, m_debug);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ private:
|
|||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static ComPtr<ID3DBlob> CompileShader(EntryType type, D3D_FEATURE_LEVEL feature_level, std::string_view code, bool debug);
|
||||
|
||||
static std::string GetCacheBaseFileName(const std::string_view& base_path, const std::string_view& type,
|
||||
D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
static CacheIndexKey GetShaderCacheKey(EntryType type, const std::string_view& shader_code);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "d3d11/shader_compiler.h"
|
||||
#include "d3d12/context.h"
|
||||
#include "d3d12/shader_cache.h"
|
||||
#include "d3d12/util.h"
|
||||
|
|
|
@ -4,14 +4,7 @@
|
|||
#include "gpu_hw_d3d11.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/timer.h"
|
||||
#include "gpu/d3d11_device.h"
|
||||
#include "gpu/gpu_device.h"
|
||||
#include "gpu_hw_shadergen.h"
|
||||
#include "gpu_sw_backend.h"
|
||||
#include "shader_cache_version.h"
|
||||
#include "system.h"
|
||||
#include "util/state_wrapper.h"
|
||||
|
||||
Log_SetChannel(GPU_HW_D3D11);
|
||||
|
||||
GPU_HW_D3D11::GPU_HW_D3D11() = default;
|
||||
|
|
|
@ -2,15 +2,8 @@
|
|||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "gpu/d3d11/shader_cache.h"
|
||||
#include "gpu/d3d11/stream_buffer.h"
|
||||
#include "gpu/d3d11_texture.h"
|
||||
#include "gpu/d3d11_device.h"
|
||||
#include "gpu_hw.h"
|
||||
#include <array>
|
||||
#include <d3d11.h>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class GPU_HW_D3D11 final : public GPU_HW
|
||||
{
|
||||
|
@ -33,7 +26,7 @@ private:
|
|||
|
||||
bool CreateTextureBuffer();
|
||||
|
||||
D3D11::StreamBuffer m_texture_stream_buffer;
|
||||
D3D11StreamBuffer m_texture_stream_buffer;
|
||||
|
||||
ComPtr<ID3D11ShaderResourceView> m_texture_stream_buffer_srv_r16ui;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "common/log.h"
|
||||
#include "common/scoped_guard.h"
|
||||
#include "common/timer.h"
|
||||
#include "gpu/d3d11/shader_compiler.h"
|
||||
#include "gpu/d3d12/context.h"
|
||||
#include "gpu/d3d12/descriptor_heap_manager.h"
|
||||
#include "gpu/d3d12/shader_cache.h"
|
||||
|
@ -214,7 +213,7 @@ void GPU_HW_D3D12::SetCapabilities()
|
|||
m_max_resolution_scale = max_texture_scale;
|
||||
|
||||
m_max_multisamples = 1;
|
||||
for (u32 multisamples = 2; multisamples < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; multisamples++)
|
||||
for (u32 multisamples = 2; multisamples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; multisamples++)
|
||||
{
|
||||
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS fd = {DXGI_FORMAT_R8G8B8A8_UNORM, static_cast<UINT>(multisamples)};
|
||||
|
||||
|
|
Loading…
Reference in New Issue