[GPU] Non-ROV f24 trunc/round, host shader modifications, cache dir

This commit is contained in:
Triang3l 2020-12-07 22:23:54 +03:00
parent a86609e93a
commit 9a4643d0f2
71 changed files with 3656 additions and 1633 deletions

View File

@ -65,6 +65,14 @@ DEFINE_path(
"Root path for guest content storage (saves, etc.), or empty to use the " "Root path for guest content storage (saves, etc.), or empty to use the "
"content folder under the storage root.", "content folder under the storage root.",
"Storage"); "Storage");
DEFINE_path(
cache_root, "",
"Root path for files used to speed up certain parts of the emulator or the "
"game. These files may be persistent, but they can be deleted without "
"major side effects such as progress loss. If empty, the cache folder "
"under the storage root, or, if available, the cache directory preferred "
"for the OS, will be used.",
"Storage");
DEFINE_bool(mount_scratch, false, "Enable scratch mount", "Storage"); DEFINE_bool(mount_scratch, false, "Enable scratch mount", "Storage");
DEFINE_bool(mount_cache, false, "Enable cache mount", "Storage"); DEFINE_bool(mount_cache, false, "Enable cache mount", "Storage");
@ -221,6 +229,8 @@ int xenia_main(const std::vector<std::string>& args) {
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_GNU_LINUX) #if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_GNU_LINUX)
storage_root = storage_root / "Xenia"; storage_root = storage_root / "Xenia";
#else #else
// TODO(Triang3l): Point to the app's external storage "files" directory
// on Android.
#warning Unhandled platform for the data root. #warning Unhandled platform for the data root.
storage_root = storage_root / "Xenia"; storage_root = storage_root / "Xenia";
#endif #endif
@ -244,13 +254,29 @@ int xenia_main(const std::vector<std::string>& args) {
content_root = std::filesystem::absolute(content_root); content_root = std::filesystem::absolute(content_root);
XELOGI("Content root: {}", xe::path_to_utf8(content_root)); XELOGI("Content root: {}", xe::path_to_utf8(content_root));
std::filesystem::path cache_root = cvars::cache_root;
if (cache_root.empty()) {
cache_root = storage_root / "cache";
// TODO(Triang3l): Point to the app's external storage "cache" directory on
// Android.
} else {
// If content root isn't an absolute path, then it should be relative to the
// storage root.
if (!cache_root.is_absolute()) {
cache_root = storage_root / cache_root;
}
}
cache_root = std::filesystem::absolute(cache_root);
XELOGI("Cache root: {}", xe::path_to_utf8(cache_root));
if (cvars::discord) { if (cvars::discord) {
discord::DiscordPresence::Initialize(); discord::DiscordPresence::Initialize();
discord::DiscordPresence::NotPlaying(); discord::DiscordPresence::NotPlaying();
} }
// Create the emulator but don't initialize so we can setup the window. // Create the emulator but don't initialize so we can setup the window.
auto emulator = std::make_unique<Emulator>("", storage_root, content_root); auto emulator =
std::make_unique<Emulator>("", storage_root, content_root, cache_root);
// Main emulator display window. // Main emulator display window.
auto emulator_window = EmulatorWindow::Create(emulator.get()); auto emulator_window = EmulatorWindow::Create(emulator.get());

View File

@ -59,13 +59,15 @@ namespace xe {
Emulator::Emulator(const std::filesystem::path& command_line, Emulator::Emulator(const std::filesystem::path& command_line,
const std::filesystem::path& storage_root, const std::filesystem::path& storage_root,
const std::filesystem::path& content_root) const std::filesystem::path& content_root,
const std::filesystem::path& cache_root)
: on_launch(), : on_launch(),
on_terminate(), on_terminate(),
on_exit(), on_exit(),
command_line_(command_line), command_line_(command_line),
storage_root_(storage_root), storage_root_(storage_root),
content_root_(content_root), content_root_(content_root),
cache_root_(cache_root),
game_title_(), game_title_(),
display_window_(nullptr), display_window_(nullptr),
memory_(), memory_(),
@ -689,7 +691,7 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
// playing before the video can be seen if doing this in parallel with the // playing before the video can be seen if doing this in parallel with the
// main thread. // main thread.
on_shader_storage_initialization(true); on_shader_storage_initialization(true);
graphics_system_->InitializeShaderStorage(storage_root_, title_id_, true); graphics_system_->InitializeShaderStorage(cache_root_, title_id_, true);
on_shader_storage_initialization(false); on_shader_storage_initialization(false);
auto main_thread = kernel_state_->LaunchModule(module); auto main_thread = kernel_state_->LaunchModule(module);

View File

@ -49,7 +49,8 @@ class Emulator {
public: public:
explicit Emulator(const std::filesystem::path& command_line, explicit Emulator(const std::filesystem::path& command_line,
const std::filesystem::path& storage_root, const std::filesystem::path& storage_root,
const std::filesystem::path& content_root); const std::filesystem::path& content_root,
const std::filesystem::path& cache_root);
~Emulator(); ~Emulator();
// Full command line used when launching the process. // Full command line used when launching the process.
@ -61,6 +62,9 @@ class Emulator {
// Folder guest content is stored in. // Folder guest content is stored in.
const std::filesystem::path& content_root() const { return content_root_; } const std::filesystem::path& content_root() const { return content_root_; }
// Folder files safe to remove without significant side effects are stored in.
const std::filesystem::path& cache_root() const { return cache_root_; }
// Title of the game in the default language. // Title of the game in the default language.
const std::string& game_title() const { return game_title_; } const std::string& game_title() const { return game_title_; }
@ -166,6 +170,7 @@ class Emulator {
std::filesystem::path command_line_; std::filesystem::path command_line_;
std::filesystem::path storage_root_; std::filesystem::path storage_root_;
std::filesystem::path content_root_; std::filesystem::path content_root_;
std::filesystem::path cache_root_;
std::string game_title_; std::string game_title_;

View File

@ -89,8 +89,8 @@ void CommandProcessor::Shutdown() {
} }
void CommandProcessor::InitializeShaderStorage( void CommandProcessor::InitializeShaderStorage(
const std::filesystem::path& storage_root, uint32_t title_id, const std::filesystem::path& cache_root, uint32_t title_id, bool blocking) {
bool blocking) {} }
void CommandProcessor::RequestFrameTrace( void CommandProcessor::RequestFrameTrace(
const std::filesystem::path& root_path) { const std::filesystem::path& root_path) {

View File

@ -133,9 +133,8 @@ class CommandProcessor {
// May be called not only from the command processor thread when the command // May be called not only from the command processor thread when the command
// processor is paused, and the termination of this function may be explicitly // processor is paused, and the termination of this function may be explicitly
// awaited. // awaited.
virtual void InitializeShaderStorage( virtual void InitializeShaderStorage(const std::filesystem::path& cache_root,
const std::filesystem::path& storage_root, uint32_t title_id, uint32_t title_id, bool blocking);
bool blocking);
virtual void RequestFrameTrace(const std::filesystem::path& root_path); virtual void RequestFrameTrace(const std::filesystem::path& root_path);
virtual void BeginTracing(const std::filesystem::path& root_path); virtual void BeginTracing(const std::filesystem::path& root_path);

View File

@ -73,10 +73,9 @@ void D3D12CommandProcessor::ClearCaches() {
} }
void D3D12CommandProcessor::InitializeShaderStorage( void D3D12CommandProcessor::InitializeShaderStorage(
const std::filesystem::path& storage_root, uint32_t title_id, const std::filesystem::path& cache_root, uint32_t title_id, bool blocking) {
bool blocking) { CommandProcessor::InitializeShaderStorage(cache_root, title_id, blocking);
CommandProcessor::InitializeShaderStorage(storage_root, title_id, blocking); pipeline_cache_->InitializeShaderStorage(cache_root, title_id, blocking);
pipeline_cache_->InitializeShaderStorage(storage_root, title_id, blocking);
} }
void D3D12CommandProcessor::RequestFrameTrace( void D3D12CommandProcessor::RequestFrameTrace(
@ -102,7 +101,7 @@ void D3D12CommandProcessor::RestoreEdramSnapshot(const void* snapshot) {
} }
uint32_t D3D12CommandProcessor::GetCurrentColorMask( uint32_t D3D12CommandProcessor::GetCurrentColorMask(
const D3D12Shader* pixel_shader) const { const Shader* pixel_shader) const {
if (pixel_shader == nullptr) { if (pixel_shader == nullptr) {
return 0; return 0;
} }
@ -159,25 +158,16 @@ void D3D12CommandProcessor::SubmitBarriers() {
} }
ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature( ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader) { const DxbcShader* vertex_shader, const DxbcShader* pixel_shader,
assert_true(vertex_shader->is_translated()); bool tessellated) {
if (bindless_resources_used_) { if (bindless_resources_used_) {
return vertex_shader->host_vertex_shader_type() != return tessellated ? root_signature_bindless_ds_
Shader::HostVertexShaderType::kVertex : root_signature_bindless_vs_;
? root_signature_bindless_ds_
: root_signature_bindless_vs_;
} }
assert_true(pixel_shader == nullptr || pixel_shader->is_translated()); D3D12_SHADER_VISIBILITY vertex_visibility =
tessellated ? D3D12_SHADER_VISIBILITY_DOMAIN
D3D12_SHADER_VISIBILITY vertex_visibility; : D3D12_SHADER_VISIBILITY_VERTEX;
if (vertex_shader->host_vertex_shader_type() !=
Shader::HostVertexShaderType::kVertex) {
vertex_visibility = D3D12_SHADER_VISIBILITY_DOMAIN;
} else {
vertex_visibility = D3D12_SHADER_VISIBILITY_VERTEX;
}
uint32_t texture_count_vertex, sampler_count_vertex; uint32_t texture_count_vertex, sampler_count_vertex;
vertex_shader->GetTextureBindings(texture_count_vertex); vertex_shader->GetTextureBindings(texture_count_vertex);
@ -393,7 +383,7 @@ ID3D12RootSignature* D3D12CommandProcessor::GetRootSignature(
} }
uint32_t D3D12CommandProcessor::GetRootBindfulExtraParameterIndices( uint32_t D3D12CommandProcessor::GetRootBindfulExtraParameterIndices(
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader, const DxbcShader* vertex_shader, const DxbcShader* pixel_shader,
RootBindfulExtraParameterIndices& indices_out) { RootBindfulExtraParameterIndices& indices_out) {
uint32_t texture_count_pixel = 0, sampler_count_pixel = 0; uint32_t texture_count_pixel = 0, sampler_count_pixel = 0;
if (pixel_shader != nullptr) { if (pixel_shader != nullptr) {
@ -1202,6 +1192,7 @@ bool D3D12CommandProcessor::SetupContext() {
pipeline_cache_ = std::make_unique<PipelineCache>( pipeline_cache_ = std::make_unique<PipelineCache>(
*this, *register_file_, bindless_resources_used_, edram_rov_used_, *this, *register_file_, bindless_resources_used_, edram_rov_used_,
render_target_cache_->depth_float24_conversion(),
texture_cache_->IsResolutionScale2X() ? 2 : 1); texture_cache_->IsResolutionScale2X() ? 2 : 1);
if (!pipeline_cache_->Initialize()) { if (!pipeline_cache_->Initialize()) {
XELOGE("Failed to initialize the graphics pipeline cache"); XELOGE("Failed to initialize the graphics pipeline cache");
@ -1804,8 +1795,7 @@ Shader* D3D12CommandProcessor::LoadShader(xenos::ShaderType shader_type,
uint32_t guest_address, uint32_t guest_address,
const uint32_t* host_address, const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
return pipeline_cache_->LoadShader(shader_type, guest_address, host_address, return pipeline_cache_->LoadShader(shader_type, host_address, dword_count);
dword_count);
} }
bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type, bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
@ -1851,21 +1841,30 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
// Need a pixel shader in normal color mode. // Need a pixel shader in normal color mode.
return false; return false;
} }
// Get tessellation info for the current draw for vertex shader translation. DxbcShaderTranslator::Modification vertex_shader_modification;
Shader::HostVertexShaderType host_vertex_shader_type = DxbcShaderTranslator::Modification pixel_shader_modification;
pipeline_cache_->GetHostVertexShaderTypeIfValid(); if (!pipeline_cache_->GetCurrentShaderModifications(
if (host_vertex_shader_type == Shader::HostVertexShaderType(-1)) { vertex_shader_modification, pixel_shader_modification)) {
return false; return false;
} }
D3D12Shader::D3D12Translation* vertex_shader_translation =
static_cast<D3D12Shader::D3D12Translation*>(
vertex_shader->GetOrCreateTranslation(
vertex_shader_modification.value));
D3D12Shader::D3D12Translation* pixel_shader_translation =
pixel_shader ? static_cast<D3D12Shader::D3D12Translation*>(
pixel_shader->GetOrCreateTranslation(
pixel_shader_modification.value))
: nullptr;
// Translate the shaders now to get memexport configuration and color mask, // Translate the shaders now to get memexport configuration and color mask,
// which is needed by the render target cache, to check the possibility of // which is needed by the render target cache, and also to get used textures
// doing early depth/stencil, and also to get used textures and samplers. // and samplers.
if (!pipeline_cache_->EnsureShadersTranslated(vertex_shader, pixel_shader, if (!pipeline_cache_->EnsureShadersTranslated(vertex_shader_translation,
host_vertex_shader_type)) { pixel_shader_translation)) {
return false; return false;
} }
bool tessellated = bool tessellated = vertex_shader_modification.host_vertex_shader_type !=
host_vertex_shader_type != Shader::HostVertexShaderType::kVertex; Shader::HostVertexShaderType::kVertex;
// Check if memexport is used. If it is, we can't skip draw calls that have no // Check if memexport is used. If it is, we can't skip draw calls that have no
// visual effect. // visual effect.
@ -1967,26 +1966,14 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
(pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0); (pixel_shader != nullptr ? pixel_shader->GetUsedTextureMask() : 0);
texture_cache_->RequestTextures(used_texture_mask); texture_cache_->RequestTextures(used_texture_mask);
// Check if early depth/stencil can be enabled.
bool early_z;
if (pixel_shader) {
auto rb_colorcontrol = regs.Get<reg::RB_COLORCONTROL>();
early_z = pixel_shader->implicit_early_z_allowed() &&
(!rb_colorcontrol.alpha_test_enable ||
rb_colorcontrol.alpha_func == xenos::CompareFunction::kAlways) &&
!rb_colorcontrol.alpha_to_mask_enable;
} else {
early_z = true;
}
// Create the pipeline if needed and bind it. // Create the pipeline if needed and bind it.
void* pipeline_handle; void* pipeline_handle;
ID3D12RootSignature* root_signature; ID3D12RootSignature* root_signature;
if (!pipeline_cache_->ConfigurePipeline( if (!pipeline_cache_->ConfigurePipeline(
vertex_shader, pixel_shader, primitive_type_converted, vertex_shader_translation, pixel_shader_translation,
primitive_type_converted,
indexed ? index_buffer_info->format : xenos::IndexFormat::kInt16, indexed ? index_buffer_info->format : xenos::IndexFormat::kInt16,
early_z, pipeline_render_targets, &pipeline_handle, pipeline_render_targets, &pipeline_handle, &root_signature)) {
&root_signature)) {
return false; return false;
} }
if (current_cached_pipeline_ != pipeline_handle) { if (current_cached_pipeline_ != pipeline_handle) {
@ -2014,11 +2001,18 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
pixel_size_x *= 2; pixel_size_x *= 2;
pixel_size_y *= 2; pixel_size_y *= 2;
} }
flags::DepthFloat24Conversion depth_float24_conversion =
render_target_cache_->depth_float24_conversion();
draw_util::ViewportInfo viewport_info; draw_util::ViewportInfo viewport_info;
draw_util::GetHostViewportInfo(regs, float(pixel_size_x), float(pixel_size_y), draw_util::GetHostViewportInfo(
true, float(D3D12_VIEWPORT_BOUNDS_MAX), regs, float(pixel_size_x), float(pixel_size_y), true,
float(D3D12_VIEWPORT_BOUNDS_MAX), false, float(D3D12_VIEWPORT_BOUNDS_MAX), float(D3D12_VIEWPORT_BOUNDS_MAX), false,
viewport_info); !edram_rov_used_ &&
(depth_float24_conversion ==
flags::DepthFloat24Conversion::kOnOutputTruncating ||
depth_float24_conversion ==
flags::DepthFloat24Conversion::kOnOutputRounding),
viewport_info);
draw_util::Scissor scissor; draw_util::Scissor scissor;
draw_util::GetScissor(regs, scissor); draw_util::GetScissor(regs, scissor);
scissor.left *= pixel_size_x; scissor.left *= pixel_size_x;
@ -2033,7 +2027,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
UpdateSystemConstantValues( UpdateSystemConstantValues(
memexport_used, primitive_polygonal, line_loop_closing_index, memexport_used, primitive_polygonal, line_loop_closing_index,
indexed ? index_buffer_info->endianness : xenos::Endian::kNone, indexed ? index_buffer_info->endianness : xenos::Endian::kNone,
viewport_info, pixel_size_x, pixel_size_y, used_texture_mask, early_z, viewport_info, pixel_size_x, pixel_size_y, used_texture_mask,
GetCurrentColorMask(pixel_shader), pipeline_render_targets); GetCurrentColorMask(pixel_shader), pipeline_render_targets);
// Update constant buffers, descriptors and root parameters. // Update constant buffers, descriptors and root parameters.
@ -2873,8 +2867,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
bool shared_memory_is_uav, bool primitive_polygonal, bool shared_memory_is_uav, bool primitive_polygonal,
uint32_t line_loop_closing_index, xenos::Endian index_endian, uint32_t line_loop_closing_index, xenos::Endian index_endian,
const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x, const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x,
uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z, uint32_t pixel_size_y, uint32_t used_texture_mask, uint32_t color_mask,
uint32_t color_mask,
const RenderTargetCache::PipelineRenderTarget render_targets[4]) { const RenderTargetCache::PipelineRenderTarget render_targets[4]) {
#if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES #if XE_UI_D3D12_FINE_GRAINED_DRAW_SCOPES
SCOPE_profile_cpu_f("gpu"); SCOPE_profile_cpu_f("gpu");
@ -2992,14 +2985,11 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
flags |= DxbcShaderTranslator::kSysFlag_KillIfAnyVertexKilled; flags |= DxbcShaderTranslator::kSysFlag_KillIfAnyVertexKilled;
} }
// Alpha test. // Alpha test.
if (rb_colorcontrol.alpha_test_enable) { xenos::CompareFunction alpha_test_function =
flags |= uint32_t(rb_colorcontrol.alpha_func) rb_colorcontrol.alpha_test_enable ? rb_colorcontrol.alpha_func
<< DxbcShaderTranslator::kSysFlag_AlphaPassIfLess_Shift; : xenos::CompareFunction::kAlways;
} else { flags |= uint32_t(alpha_test_function)
flags |= DxbcShaderTranslator::kSysFlag_AlphaPassIfLess | << DxbcShaderTranslator::kSysFlag_AlphaPassIfLess_Shift;
DxbcShaderTranslator::kSysFlag_AlphaPassIfEqual |
DxbcShaderTranslator::kSysFlag_AlphaPassIfGreater;
}
// Gamma writing. // Gamma writing.
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
if (color_infos[i].color_format == if (color_infos[i].color_format ==
@ -3028,7 +3018,9 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
if (rb_depthcontrol.stencil_enable) { if (rb_depthcontrol.stencil_enable) {
flags |= DxbcShaderTranslator::kSysFlag_ROVStencilTest; flags |= DxbcShaderTranslator::kSysFlag_ROVStencilTest;
} }
if (early_z) { // Hint - if not applicable to the shader, will not have effect.
if (alpha_test_function == xenos::CompareFunction::kAlways &&
!rb_colorcontrol.alpha_to_mask_enable) {
flags |= DxbcShaderTranslator::kSysFlag_ROVDepthStencilEarlyWrite; flags |= DxbcShaderTranslator::kSysFlag_ROVDepthStencilEarlyWrite;
} }
} }

View File

@ -27,6 +27,7 @@
#include "xenia/gpu/d3d12/render_target_cache.h" #include "xenia/gpu/d3d12/render_target_cache.h"
#include "xenia/gpu/d3d12/texture_cache.h" #include "xenia/gpu/d3d12/texture_cache.h"
#include "xenia/gpu/draw_util.h" #include "xenia/gpu/draw_util.h"
#include "xenia/gpu/dxbc_shader.h"
#include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
@ -47,7 +48,7 @@ class D3D12CommandProcessor : public CommandProcessor {
void ClearCaches() override; void ClearCaches() override;
void InitializeShaderStorage(const std::filesystem::path& storage_root, void InitializeShaderStorage(const std::filesystem::path& cache_root,
uint32_t title_id, bool blocking) override; uint32_t title_id, bool blocking) override;
void RequestFrameTrace(const std::filesystem::path& root_path) override; void RequestFrameTrace(const std::filesystem::path& root_path) override;
@ -88,7 +89,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// there are 4 render targets bound with the same EDRAM base (clearly not // there are 4 render targets bound with the same EDRAM base (clearly not
// correct usage), but the shader only clears 1, and then EDRAM buffer stores // correct usage), but the shader only clears 1, and then EDRAM buffer stores
// conflict with each other. // conflict with each other.
uint32_t GetCurrentColorMask(const D3D12Shader* pixel_shader) const; uint32_t GetCurrentColorMask(const Shader* pixel_shader) const;
void PushTransitionBarrier( void PushTransitionBarrier(
ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state, ID3D12Resource* resource, D3D12_RESOURCE_STATES old_state,
@ -100,8 +101,9 @@ class D3D12CommandProcessor : public CommandProcessor {
void SubmitBarriers(); void SubmitBarriers();
// Finds or creates root signature for a pipeline. // Finds or creates root signature for a pipeline.
ID3D12RootSignature* GetRootSignature(const D3D12Shader* vertex_shader, ID3D12RootSignature* GetRootSignature(const DxbcShader* vertex_shader,
const D3D12Shader* pixel_shader); const DxbcShader* pixel_shader,
bool tessellated);
ui::d3d12::D3D12UploadBufferPool& GetConstantBufferPool() const { ui::d3d12::D3D12UploadBufferPool& GetConstantBufferPool() const {
return *constant_buffer_pool_; return *constant_buffer_pool_;
@ -300,7 +302,7 @@ class D3D12CommandProcessor : public CommandProcessor {
// Gets the indices of optional root parameters. Returns the total parameter // Gets the indices of optional root parameters. Returns the total parameter
// count. // count.
static uint32_t GetRootBindfulExtraParameterIndices( static uint32_t GetRootBindfulExtraParameterIndices(
const D3D12Shader* vertex_shader, const D3D12Shader* pixel_shader, const DxbcShader* vertex_shader, const DxbcShader* pixel_shader,
RootBindfulExtraParameterIndices& indices_out); RootBindfulExtraParameterIndices& indices_out);
// BeginSubmission and EndSubmission may be called at any time. If there's an // BeginSubmission and EndSubmission may be called at any time. If there's an
@ -353,8 +355,7 @@ class D3D12CommandProcessor : public CommandProcessor {
bool shared_memory_is_uav, bool primitive_polygonal, bool shared_memory_is_uav, bool primitive_polygonal,
uint32_t line_loop_closing_index, xenos::Endian index_endian, uint32_t line_loop_closing_index, xenos::Endian index_endian,
const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x, const draw_util::ViewportInfo& viewport_info, uint32_t pixel_size_x,
uint32_t pixel_size_y, uint32_t used_texture_mask, bool early_z, uint32_t pixel_size_y, uint32_t used_texture_mask, uint32_t color_mask,
uint32_t color_mask,
const RenderTargetCache::PipelineRenderTarget render_targets[4]); const RenderTargetCache::PipelineRenderTarget render_targets[4]);
bool UpdateBindings(const D3D12Shader* vertex_shader, bool UpdateBindings(const D3D12Shader* vertex_shader,
const D3D12Shader* pixel_shader, const D3D12Shader* pixel_shader,

View File

@ -10,9 +10,11 @@
#include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/d3d12/d3d12_shader.h"
#include <cstring> #include <cstring>
#include <utility>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/gpu/dxbc_shader.h"
#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/gpu_flags.h"
#include "xenia/ui/d3d12/d3d12_api.h" #include "xenia/ui/d3d12/d3d12_api.h"
@ -22,51 +24,13 @@ namespace d3d12 {
D3D12Shader::D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash, D3D12Shader::D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count) const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count) {} : DxbcShader(shader_type, data_hash, dword_ptr, dword_count) {}
void D3D12Shader::SetTexturesAndSamplers( void D3D12Shader::D3D12Translation::DisassembleDxbcAndDxil(
const DxbcShaderTranslator::TextureBinding* texture_bindings, const ui::d3d12::D3D12Provider& provider, bool disassemble_dxbc,
uint32_t texture_binding_count, IDxbcConverter* dxbc_converter, IDxcUtils* dxc_utils,
const DxbcShaderTranslator::SamplerBinding* sampler_bindings, IDxcCompiler* dxc_compiler) {
uint32_t sampler_binding_count) { std::string disassembly;
texture_bindings_.clear();
texture_bindings_.reserve(texture_binding_count);
used_texture_mask_ = 0;
for (uint32_t i = 0; i < texture_binding_count; ++i) {
TextureBinding& binding = texture_bindings_.emplace_back();
// For a stable hash.
std::memset(&binding, 0, sizeof(binding));
const DxbcShaderTranslator::TextureBinding& translator_binding =
texture_bindings[i];
binding.bindless_descriptor_index =
translator_binding.bindless_descriptor_index;
binding.fetch_constant = translator_binding.fetch_constant;
binding.dimension = translator_binding.dimension;
binding.is_signed = translator_binding.is_signed;
used_texture_mask_ |= 1u << translator_binding.fetch_constant;
}
sampler_bindings_.clear();
sampler_bindings_.reserve(sampler_binding_count);
for (uint32_t i = 0; i < sampler_binding_count; ++i) {
SamplerBinding binding;
const DxbcShaderTranslator::SamplerBinding& translator_binding =
sampler_bindings[i];
binding.bindless_descriptor_index =
translator_binding.bindless_descriptor_index;
binding.fetch_constant = translator_binding.fetch_constant;
binding.mag_filter = translator_binding.mag_filter;
binding.min_filter = translator_binding.min_filter;
binding.mip_filter = translator_binding.mip_filter;
binding.aniso_filter = translator_binding.aniso_filter;
sampler_bindings_.push_back(binding);
}
}
void D3D12Shader::DisassembleDxbc(const ui::d3d12::D3D12Provider& provider,
bool disassemble_dxbc,
IDxbcConverter* dxbc_converter,
IDxcUtils* dxc_utils,
IDxcCompiler* dxc_compiler) {
bool is_first_disassembly = true; bool is_first_disassembly = true;
if (disassemble_dxbc) { if (disassemble_dxbc) {
ID3DBlob* dxbc_disassembly; ID3DBlob* dxbc_disassembly;
@ -77,11 +41,12 @@ void D3D12Shader::DisassembleDxbc(const ui::d3d12::D3D12Provider& provider,
nullptr, &dxbc_disassembly))) { nullptr, &dxbc_disassembly))) {
assert_true(is_first_disassembly); assert_true(is_first_disassembly);
is_first_disassembly = false; is_first_disassembly = false;
host_disassembly_.append( disassembly.append(
reinterpret_cast<const char*>(dxbc_disassembly->GetBufferPointer())); reinterpret_cast<const char*>(dxbc_disassembly->GetBufferPointer()));
dxbc_disassembly->Release(); dxbc_disassembly->Release();
} else { } else {
XELOGE("Failed to disassemble DXBC shader {:016X}", ucode_data_hash()); XELOGE("Failed to disassemble DXBC shader {:016X}",
shader().ucode_data_hash());
} }
} }
if (dxbc_converter && dxc_utils && dxc_compiler) { if (dxbc_converter && dxc_utils && dxc_compiler) {
@ -106,29 +71,36 @@ void D3D12Shader::DisassembleDxbc(const ui::d3d12::D3D12Provider& provider,
dxil_disassembly->Release(); dxil_disassembly->Release();
if (dxil_disassembly_got_utf8) { if (dxil_disassembly_got_utf8) {
if (!is_first_disassembly) { if (!is_first_disassembly) {
host_disassembly_.append("\n\n"); disassembly.append("\n\n");
} }
is_first_disassembly = false; is_first_disassembly = false;
host_disassembly_.append(reinterpret_cast<const char*>( disassembly.append(reinterpret_cast<const char*>(
dxil_disassembly_utf8->GetStringPointer())); dxil_disassembly_utf8->GetStringPointer()));
dxil_disassembly_utf8->Release(); dxil_disassembly_utf8->Release();
} else { } else {
XELOGE("Failed to get DXIL shader {:016X} disassembly as UTF-8", XELOGE("Failed to get DXIL shader {:016X} disassembly as UTF-8",
ucode_data_hash()); shader().ucode_data_hash());
} }
} else { } else {
XELOGE("Failed to disassemble DXIL shader {:016X}", XELOGE("Failed to disassemble DXIL shader {:016X}",
ucode_data_hash()); shader().ucode_data_hash());
} }
} else { } else {
XELOGE("Failed to create a blob with DXIL shader {:016X}", XELOGE("Failed to create a blob with DXIL shader {:016X}",
ucode_data_hash()); shader().ucode_data_hash());
CoTaskMemFree(dxil); CoTaskMemFree(dxil);
} }
} else { } else {
XELOGE("Failed to convert shader {:016X} to DXIL", ucode_data_hash()); XELOGE("Failed to convert shader {:016X} to DXIL",
shader().ucode_data_hash());
} }
} }
set_host_disassembly(std::move(disassembly));
}
Shader::Translation* D3D12Shader::CreateTranslationInstance(
uint32_t modification) {
return new D3D12Translation(*this, modification);
} }
} // namespace d3d12 } // namespace d3d12

View File

@ -2,7 +2,7 @@
****************************************************************************** ******************************************************************************
* Xenia : Xbox 360 Emulator Research Project * * Xenia : Xbox 360 Emulator Research Project *
****************************************************************************** ******************************************************************************
* Copyright 2018 Ben Vanik. All rights reserved. * * Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. * * Released under the BSD license - see LICENSE in the root for more details. *
****************************************************************************** ******************************************************************************
*/ */
@ -10,106 +10,62 @@
#ifndef XENIA_GPU_D3D12_D3D12_SHADER_H_ #ifndef XENIA_GPU_D3D12_D3D12_SHADER_H_
#define XENIA_GPU_D3D12_D3D12_SHADER_H_ #define XENIA_GPU_D3D12_D3D12_SHADER_H_
#include <vector> #include <atomic>
#include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/dxbc_shader.h"
#include "xenia/gpu/shader.h"
#include "xenia/gpu/xenos.h"
#include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/d3d12/d3d12_provider.h"
namespace xe { namespace xe {
namespace gpu { namespace gpu {
namespace d3d12 { namespace d3d12 {
class D3D12Shader : public Shader { class D3D12Shader : public DxbcShader {
public: public:
class D3D12Translation : public DxbcTranslation {
public:
D3D12Translation(D3D12Shader& shader, uint32_t modification)
: DxbcTranslation(shader, modification) {}
void DisassembleDxbcAndDxil(const ui::d3d12::D3D12Provider& provider,
bool disassemble_dxbc,
IDxbcConverter* dxbc_converter = nullptr,
IDxcUtils* dxc_utils = nullptr,
IDxcCompiler* dxc_compiler = nullptr);
};
D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash, D3D12Shader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count); const uint32_t* dword_ptr, uint32_t dword_count);
void SetTexturesAndSamplers( // For owning subsystem like the pipeline cache, accessors for unique
const DxbcShaderTranslator::TextureBinding* texture_bindings,
uint32_t texture_binding_count,
const DxbcShaderTranslator::SamplerBinding* sampler_bindings,
uint32_t sampler_binding_count);
void SetForcedEarlyZShaderObject(const std::vector<uint8_t>& shader_object) {
forced_early_z_shader_ = shader_object;
}
// Returns the shader with forced early depth/stencil set with
// SetForcedEarlyZShader after translation. If there's none (for example,
// if the shader discards pixels or writes to the depth buffer), an empty
// vector is returned.
const std::vector<uint8_t>& GetForcedEarlyZShaderObject() const {
return forced_early_z_shader_;
}
void DisassembleDxbc(const ui::d3d12::D3D12Provider& provider,
bool disassemble_dxbc,
IDxbcConverter* dxbc_converter = nullptr,
IDxcUtils* dxc_utils = nullptr,
IDxcCompiler* dxc_compiler = nullptr);
static constexpr uint32_t kMaxTextureBindingIndexBits =
DxbcShaderTranslator::kMaxTextureBindingIndexBits;
static constexpr uint32_t kMaxTextureBindings =
DxbcShaderTranslator::kMaxTextureBindings;
struct TextureBinding {
uint32_t bindless_descriptor_index;
uint32_t fetch_constant;
// Stacked and 3D are separate TextureBindings, even for bindless for null
// descriptor handling simplicity.
xenos::FetchOpDimension dimension;
bool is_signed;
};
// Safe to hash and compare with memcmp for layout hashing.
const TextureBinding* GetTextureBindings(uint32_t& count_out) const {
count_out = uint32_t(texture_bindings_.size());
return texture_bindings_.data();
}
const uint32_t GetUsedTextureMask() const { return used_texture_mask_; }
static constexpr uint32_t kMaxSamplerBindingIndexBits =
DxbcShaderTranslator::kMaxSamplerBindingIndexBits;
static constexpr uint32_t kMaxSamplerBindings =
DxbcShaderTranslator::kMaxSamplerBindings;
struct SamplerBinding {
uint32_t bindless_descriptor_index;
uint32_t fetch_constant;
xenos::TextureFilter mag_filter;
xenos::TextureFilter min_filter;
xenos::TextureFilter mip_filter;
xenos::AnisoFilter aniso_filter;
};
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
count_out = uint32_t(sampler_bindings_.size());
return sampler_bindings_.data();
}
// For owning subsystems like the pipeline cache, accessors for unique
// identifiers (used instead of hashes to make sure collisions can't happen) // identifiers (used instead of hashes to make sure collisions can't happen)
// of binding layouts used by the shader, for invalidation if a shader with an // of binding layouts used by the shader, for invalidation if a shader with an
// incompatible layout was bound. // incompatible layout was bound.
size_t GetTextureBindingLayoutUserUID() const { size_t GetTextureBindingLayoutUserUID() const {
return texture_binding_layout_user_uid_; return texture_binding_layout_user_uid_;
} }
void SetTextureBindingLayoutUserUID(size_t uid) {
texture_binding_layout_user_uid_ = uid;
}
size_t GetSamplerBindingLayoutUserUID() const { size_t GetSamplerBindingLayoutUserUID() const {
return sampler_binding_layout_user_uid_; return sampler_binding_layout_user_uid_;
} }
// Modifications of the same shader can be translated on different threads.
// The "set" function must only be called if "enter" returned true - these are
// set up only once.
bool EnterBindingLayoutUserUIDSetup() {
return !binding_layout_user_uids_set_up_.test_and_set();
}
void SetTextureBindingLayoutUserUID(size_t uid) {
texture_binding_layout_user_uid_ = uid;
}
void SetSamplerBindingLayoutUserUID(size_t uid) { void SetSamplerBindingLayoutUserUID(size_t uid) {
sampler_binding_layout_user_uid_ = uid; sampler_binding_layout_user_uid_ = uid;
} }
protected:
Translation* CreateTranslationInstance(uint32_t modification) override;
private: private:
std::vector<TextureBinding> texture_bindings_; std::atomic_flag binding_layout_user_uids_set_up_ = ATOMIC_FLAG_INIT;
std::vector<SamplerBinding> sampler_bindings_;
size_t texture_binding_layout_user_uid_ = 0; size_t texture_binding_layout_user_uid_ = 0;
size_t sampler_binding_layout_user_uid_ = 0; size_t sampler_binding_layout_user_uid_ = 0;
uint32_t used_texture_mask_ = 0;
std::vector<uint8_t> forced_early_z_shader_;
}; };
} // namespace d3d12 } // namespace d3d12

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
#include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/d3d12/render_target_cache.h" #include "xenia/gpu/d3d12/render_target_cache.h"
#include "xenia/gpu/dxbc_shader_translator.h" #include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/gpu_flags.h"
#include "xenia/gpu/register_file.h" #include "xenia/gpu/register_file.h"
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
#include "xenia/ui/d3d12/d3d12_api.h" #include "xenia/ui/d3d12/d3d12_api.h"
@ -43,36 +44,39 @@ class PipelineCache {
PipelineCache(D3D12CommandProcessor& command_processor, PipelineCache(D3D12CommandProcessor& command_processor,
const RegisterFile& register_file, bool bindless_resources_used, const RegisterFile& register_file, bool bindless_resources_used,
bool edram_rov_used, uint32_t resolution_scale); bool edram_rov_used,
flags::DepthFloat24Conversion depth_float24_conversion,
uint32_t resolution_scale);
~PipelineCache(); ~PipelineCache();
bool Initialize(); bool Initialize();
void Shutdown(); void Shutdown();
void ClearCache(bool shutting_down = false); void ClearCache(bool shutting_down = false);
void InitializeShaderStorage(const std::filesystem::path& storage_root, void InitializeShaderStorage(const std::filesystem::path& cache_root,
uint32_t title_id, bool blocking); uint32_t title_id, bool blocking);
void ShutdownShaderStorage(); void ShutdownShaderStorage();
void EndSubmission(); void EndSubmission();
bool IsCreatingPipelines(); bool IsCreatingPipelines();
D3D12Shader* LoadShader(xenos::ShaderType shader_type, uint32_t guest_address, D3D12Shader* LoadShader(xenos::ShaderType shader_type,
const uint32_t* host_address, uint32_t dword_count); const uint32_t* host_address, uint32_t dword_count);
// Returns the host vertex shader type for the current draw if it's valid and // Retrieves the shader modifications for the current state, and returns
// supported, or Shader::HostVertexShaderType(-1) if not. // whether they are valid.
Shader::HostVertexShaderType GetHostVertexShaderTypeIfValid() const; bool GetCurrentShaderModifications(
DxbcShaderTranslator::Modification& vertex_shader_modification_out,
DxbcShaderTranslator::Modification& pixel_shader_modification_out) const;
// Translates shaders if needed, also making shader info up to date. // Translates shaders if needed, also making shader info up to date.
bool EnsureShadersTranslated( bool EnsureShadersTranslated(D3D12Shader::D3D12Translation* vertex_shader,
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader, D3D12Shader::D3D12Translation* pixel_shader);
Shader::HostVertexShaderType host_vertex_shader_type);
bool ConfigurePipeline( bool ConfigurePipeline(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader, D3D12Shader::D3D12Translation* vertex_shader,
D3D12Shader::D3D12Translation* pixel_shader,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format, xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5], const RenderTargetCache::PipelineRenderTarget render_targets[5],
void** pipeline_handle_out, ID3D12RootSignature** root_signature_out); void** pipeline_handle_out, ID3D12RootSignature** root_signature_out);
@ -86,13 +90,12 @@ class PipelineCache {
XEPACKEDSTRUCT(ShaderStoredHeader, { XEPACKEDSTRUCT(ShaderStoredHeader, {
uint64_t ucode_data_hash; uint64_t ucode_data_hash;
uint32_t ucode_dword_count : 16; uint32_t ucode_dword_count : 31;
xenos::ShaderType type : 1; xenos::ShaderType type : 1;
Shader::HostVertexShaderType host_vertex_shader_type : 3;
reg::SQ_PROGRAM_CNTL sq_program_cntl; reg::SQ_PROGRAM_CNTL sq_program_cntl;
static constexpr uint32_t kVersion = 0x20200405; static constexpr uint32_t kVersion = 0x20201129;
}); });
// Update PipelineDescription::kVersion if any of the Pipeline* enums are // Update PipelineDescription::kVersion if any of the Pipeline* enums are
@ -170,28 +173,28 @@ class PipelineCache {
uint64_t vertex_shader_hash; uint64_t vertex_shader_hash;
// 0 if drawing without a pixel shader. // 0 if drawing without a pixel shader.
uint64_t pixel_shader_hash; uint64_t pixel_shader_hash;
uint32_t vertex_shader_modification;
uint32_t pixel_shader_modification;
int32_t depth_bias; int32_t depth_bias;
float depth_bias_slope_scaled; float depth_bias_slope_scaled;
PipelineStripCutIndex strip_cut_index : 2; // 2 PipelineStripCutIndex strip_cut_index : 2; // 2
Shader::HostVertexShaderType host_vertex_shader_type : 3; // 5
// PipelinePrimitiveTopologyType for a vertex shader. // PipelinePrimitiveTopologyType for a vertex shader.
// xenos::TessellationMode for a domain shader. // xenos::TessellationMode for a domain shader.
uint32_t primitive_topology_type_or_tessellation_mode : 2; // 7 uint32_t primitive_topology_type_or_tessellation_mode : 2; // 4
// Zero for non-kVertex host_vertex_shader_type. // Zero for non-kVertex host_vertex_shader_type.
PipelineGeometryShader geometry_shader : 2; // 9 PipelineGeometryShader geometry_shader : 2; // 6
uint32_t fill_mode_wireframe : 1; // 10 uint32_t fill_mode_wireframe : 1; // 7
PipelineCullMode cull_mode : 2; // 12 PipelineCullMode cull_mode : 2; // 9
uint32_t front_counter_clockwise : 1; // 13 uint32_t front_counter_clockwise : 1; // 10
uint32_t depth_clip : 1; // 14 uint32_t depth_clip : 1; // 11
uint32_t rov_msaa : 1; // 15 uint32_t rov_msaa : 1; // 12
xenos::DepthRenderTargetFormat depth_format : 1; // 16 xenos::DepthRenderTargetFormat depth_format : 1; // 13
xenos::CompareFunction depth_func : 3; // 19 xenos::CompareFunction depth_func : 3; // 16
uint32_t depth_write : 1; // 20 uint32_t depth_write : 1; // 17
uint32_t stencil_enable : 1; // 21 uint32_t stencil_enable : 1; // 18
uint32_t stencil_read_mask : 8; // 29 uint32_t stencil_read_mask : 8; // 26
uint32_t force_early_z : 1; // 30
uint32_t stencil_write_mask : 8; // 8 uint32_t stencil_write_mask : 8; // 8
xenos::StencilOp stencil_front_fail_op : 3; // 11 xenos::StencilOp stencil_front_fail_op : 3; // 11
@ -205,7 +208,7 @@ class PipelineCache {
PipelineRenderTarget render_targets[4]; PipelineRenderTarget render_targets[4];
static constexpr uint32_t kVersion = 0x20200405; static constexpr uint32_t kVersion = 0x20201202;
}); });
XEPACKEDSTRUCT(PipelineStoredDescription, { XEPACKEDSTRUCT(PipelineStoredDescription, {
@ -215,24 +218,31 @@ class PipelineCache {
struct PipelineRuntimeDescription { struct PipelineRuntimeDescription {
ID3D12RootSignature* root_signature; ID3D12RootSignature* root_signature;
D3D12Shader* vertex_shader; D3D12Shader::D3D12Translation* vertex_shader;
D3D12Shader* pixel_shader; D3D12Shader::D3D12Translation* pixel_shader;
PipelineDescription description; PipelineDescription description;
}; };
// Returns the host vertex shader type for the current draw if it's valid and
// supported, or Shader::HostVertexShaderType(-1) if not.
Shader::HostVertexShaderType GetCurrentHostVertexShaderTypeIfValid() const;
D3D12Shader* LoadShader(xenos::ShaderType shader_type,
const uint32_t* host_address, uint32_t dword_count,
uint64_t data_hash);
// Can be called from multiple threads. // Can be called from multiple threads.
bool TranslateShader(DxbcShaderTranslator& translator, D3D12Shader& shader, bool TranslateShader(DxbcShaderTranslator& translator,
D3D12Shader::D3D12Translation& translation,
reg::SQ_PROGRAM_CNTL cntl, reg::SQ_PROGRAM_CNTL cntl,
IDxbcConverter* dxbc_converter = nullptr, IDxbcConverter* dxbc_converter = nullptr,
IDxcUtils* dxc_utils = nullptr, IDxcUtils* dxc_utils = nullptr,
IDxcCompiler* dxc_compiler = nullptr, IDxcCompiler* dxc_compiler = nullptr);
Shader::HostVertexShaderType host_vertex_shader_type =
Shader::HostVertexShaderType::kVertex);
bool GetCurrentStateDescription( bool GetCurrentStateDescription(
D3D12Shader* vertex_shader, D3D12Shader* pixel_shader, D3D12Shader::D3D12Translation* vertex_shader,
D3D12Shader::D3D12Translation* pixel_shader,
xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format, xenos::PrimitiveType primitive_type, xenos::IndexFormat index_format,
bool early_z,
const RenderTargetCache::PipelineRenderTarget render_targets[5], const RenderTargetCache::PipelineRenderTarget render_targets[5],
PipelineRuntimeDescription& runtime_description_out); PipelineRuntimeDescription& runtime_description_out);
@ -243,6 +253,8 @@ class PipelineCache {
const RegisterFile& register_file_; const RegisterFile& register_file_;
bool bindless_resources_used_; bool bindless_resources_used_;
bool edram_rov_used_; bool edram_rov_used_;
// 20e4 depth conversion mode to use for non-ROV output.
flags::DepthFloat24Conversion depth_float24_conversion_;
uint32_t resolution_scale_; uint32_t resolution_scale_;
// Reusable shader translator. // Reusable shader translator.
@ -300,11 +312,14 @@ class PipelineCache {
Pipeline* current_pipeline_ = nullptr; Pipeline* current_pipeline_ = nullptr;
// Currently open shader storage path. // Currently open shader storage path.
std::filesystem::path shader_storage_root_; std::filesystem::path shader_storage_cache_root_;
uint32_t shader_storage_title_id_ = 0; uint32_t shader_storage_title_id_ = 0;
// Shader storage output stream, for preload in the next emulator runs. // Shader storage output stream, for preload in the next emulator runs.
FILE* shader_storage_file_ = nullptr; FILE* shader_storage_file_ = nullptr;
// For only writing shaders to the currently open storage once, incremented
// when switching the storage.
uint32_t shader_storage_index_ = 0;
bool shader_storage_file_flush_needed_ = false; bool shader_storage_file_flush_needed_ = false;
// Pipeline storage output stream, for preload in the next emulator runs. // Pipeline storage output stream, for preload in the next emulator runs.

View File

@ -40,11 +40,13 @@ namespace d3d12 {
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_32bpp_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_64bpp_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_load_color_7e3_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float24and32_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_float_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_load_depth_unorm_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_32bpp_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_64bpp_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_store_color_7e3_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float24and32_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_float_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/edram_store_depth_unorm_cs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.h" #include "xenia/gpu/d3d12/shaders/dxbc/resolve_clear_32bpp_2xres_cs.h"
@ -87,6 +89,12 @@ const RenderTargetCache::EdramLoadStoreModeInfo
{edram_load_depth_float_cs, sizeof(edram_load_depth_float_cs), {edram_load_depth_float_cs, sizeof(edram_load_depth_float_cs),
L"EDRAM Load Float Depth", edram_store_depth_float_cs, L"EDRAM Load Float Depth", edram_store_depth_float_cs,
sizeof(edram_store_depth_float_cs), L"EDRAM Store Float Depth"}, sizeof(edram_store_depth_float_cs), L"EDRAM Store Float Depth"},
{edram_load_depth_float24and32_cs,
sizeof(edram_load_depth_float24and32_cs),
L"EDRAM Load 24-bit & 32-bit Float Depth",
edram_store_depth_float24and32_cs,
sizeof(edram_store_depth_float24and32_cs),
L"EDRAM Store 24-bit & 32-bit Float Depth"},
}; };
const std::pair<const uint8_t*, size_t> const std::pair<const uint8_t*, size_t>
@ -126,6 +134,8 @@ RenderTargetCache::RenderTargetCache(D3D12CommandProcessor& command_processor,
RenderTargetCache::~RenderTargetCache() { Shutdown(); } RenderTargetCache::~RenderTargetCache() { Shutdown(); }
bool RenderTargetCache::Initialize(const TextureCache& texture_cache) { bool RenderTargetCache::Initialize(const TextureCache& texture_cache) {
depth_float24_conversion_ = flags::GetDepthFloat24Conversion();
// EDRAM buffer size depends on this. // EDRAM buffer size depends on this.
resolution_scale_2x_ = texture_cache.IsResolutionScale2X(); resolution_scale_2x_ = texture_cache.IsResolutionScale2X();
assert_false(resolution_scale_2x_ && !edram_rov_used_); assert_false(resolution_scale_2x_ && !edram_rov_used_);
@ -420,7 +430,8 @@ bool RenderTargetCache::Initialize(const TextureCache& texture_cache) {
return false; return false;
} }
resolve_clear_64bpp_pipeline_->SetName(L"Resolve Clear 64bpp"); resolve_clear_64bpp_pipeline_->SetName(L"Resolve Clear 64bpp");
if (!edram_rov_used_) { if (!edram_rov_used_ &&
depth_float24_conversion_ == flags::DepthFloat24Conversion::kOnCopy) {
assert_false(resolution_scale_2x_); assert_false(resolution_scale_2x_);
resolve_clear_depth_24_32_pipeline_ = resolve_clear_depth_24_32_pipeline_ =
ui::d3d12::util::CreateComputePipeline( ui::d3d12::util::CreateComputePipeline(
@ -434,7 +445,7 @@ bool RenderTargetCache::Initialize(const TextureCache& texture_cache) {
Shutdown(); Shutdown();
return false; return false;
} }
resolve_clear_64bpp_pipeline_->SetName( resolve_clear_depth_24_32_pipeline_->SetName(
L"Resolve Clear 24-bit & 32-bit Depth"); L"Resolve Clear 24-bit & 32-bit Depth");
} }
@ -1266,10 +1277,12 @@ bool RenderTargetCache::Resolve(const Memory& memory,
if (clear_depth) { if (clear_depth) {
// Also clear the host 32-bit floating-point depth used for loaing and // Also clear the host 32-bit floating-point depth used for loaing and
// storing 24-bit floating-point depth at full precision. // storing 24-bit floating-point depth at full precision.
bool clear_float32_depth = bool clear_float32_depth = !edram_rov_used_ &&
!edram_rov_used_ && xenos::DepthRenderTargetFormat( depth_float24_conversion_ ==
resolve_info.depth_edram_info.format) == flags::DepthFloat24Conversion::kOnCopy &&
xenos::DepthRenderTargetFormat::kD24FS8; xenos::DepthRenderTargetFormat(
resolve_info.depth_edram_info.format) ==
xenos::DepthRenderTargetFormat::kD24FS8;
draw_util::ResolveClearShaderConstants depth_clear_constants; draw_util::ResolveClearShaderConstants depth_clear_constants;
resolve_info.GetDepthClearShaderConstants(clear_float32_depth, resolve_info.GetDepthClearShaderConstants(clear_float32_depth,
depth_clear_constants); depth_clear_constants);
@ -1558,7 +1571,8 @@ void RenderTargetCache::RestoreEdramSnapshot(const void* snapshot) {
uint32_t RenderTargetCache::GetEdramBufferSize() const { uint32_t RenderTargetCache::GetEdramBufferSize() const {
uint32_t size = xenos::kEdramSizeBytes; uint32_t size = xenos::kEdramSizeBytes;
if (!edram_rov_used_) { if (!edram_rov_used_ &&
depth_float24_conversion_ == flags::DepthFloat24Conversion::kOnCopy) {
// Two 10 MB pages, one containing color and integer depth data, another // Two 10 MB pages, one containing color and integer depth data, another
// with 32-bit float depth when 20e4 depth is used to allow for multipass // with 32-bit float depth when 20e4 depth is used to allow for multipass
// drawing without precision loss in case of EDRAM store/load. // drawing without precision loss in case of EDRAM store/load.
@ -1831,12 +1845,15 @@ RenderTargetCache::RenderTarget* RenderTargetCache::FindOrCreateRenderTarget(
} }
RenderTargetCache::EdramLoadStoreMode RenderTargetCache::GetLoadStoreMode( RenderTargetCache::EdramLoadStoreMode RenderTargetCache::GetLoadStoreMode(
bool is_depth, uint32_t format) { bool is_depth, uint32_t format) const {
if (is_depth) { if (is_depth) {
return xenos::DepthRenderTargetFormat(format) == if (xenos::DepthRenderTargetFormat(format) ==
xenos::DepthRenderTargetFormat::kD24FS8 xenos::DepthRenderTargetFormat::kD24FS8) {
? EdramLoadStoreMode::kDepthFloat return depth_float24_conversion_ == flags::DepthFloat24Conversion::kOnCopy
: EdramLoadStoreMode::kDepthUnorm; ? EdramLoadStoreMode::kDepthFloat24And32
: EdramLoadStoreMode::kDepthFloat;
}
return EdramLoadStoreMode::kDepthUnorm;
} }
xenos::ColorRenderTargetFormat color_format = xenos::ColorRenderTargetFormat color_format =
xenos::ColorRenderTargetFormat(format); xenos::ColorRenderTargetFormat(format);

View File

@ -18,6 +18,7 @@
#include "xenia/gpu/d3d12/d3d12_shared_memory.h" #include "xenia/gpu/d3d12/d3d12_shared_memory.h"
#include "xenia/gpu/d3d12/texture_cache.h" #include "xenia/gpu/d3d12/texture_cache.h"
#include "xenia/gpu/draw_util.h" #include "xenia/gpu/draw_util.h"
#include "xenia/gpu/gpu_flags.h"
#include "xenia/gpu/register_file.h" #include "xenia/gpu/register_file.h"
#include "xenia/gpu/trace_writer.h" #include "xenia/gpu/trace_writer.h"
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
@ -259,6 +260,10 @@ class RenderTargetCache {
void Shutdown(); void Shutdown();
void ClearCache(); void ClearCache();
flags::DepthFloat24Conversion depth_float24_conversion() const {
return depth_float24_conversion_;
}
void CompletedSubmissionUpdated(); void CompletedSubmissionUpdated();
void BeginSubmission(); void BeginSubmission();
void EndFrame(); void EndFrame();
@ -318,6 +323,7 @@ class RenderTargetCache {
kColor7e3, kColor7e3,
kDepthUnorm, kDepthUnorm,
kDepthFloat, kDepthFloat,
kDepthFloat24And32,
kCount kCount
}; };
@ -424,7 +430,7 @@ class RenderTargetCache {
uint32_t instance); uint32_t instance);
#endif #endif
static EdramLoadStoreMode GetLoadStoreMode(bool is_depth, uint32_t format); EdramLoadStoreMode GetLoadStoreMode(bool is_depth, uint32_t format) const;
// Must be in a frame to call. Stores the dirty areas of the currently bound // Must be in a frame to call. Stores the dirty areas of the currently bound
// render targets and marks them as clean. // render targets and marks them as clean.
@ -442,6 +448,9 @@ class RenderTargetCache {
bool bindless_resources_used_; bool bindless_resources_used_;
bool edram_rov_used_; bool edram_rov_used_;
// 20e4 depth conversion mode to use for non-ROV output.
flags::DepthFloat24Conversion depth_float24_conversion_;
// Whether 1 guest pixel is rendered as 2x2 host pixels (currently only // Whether 1 guest pixel is rendered as 2x2 host pixels (currently only
// supported with ROV). // supported with ROV).
bool resolution_scale_2x_ = false; bool resolution_scale_2x_ = false;

View File

@ -0,0 +1,296 @@
// generated from `xb buildhlsl`
// source: edram_load_depth_float24and32.cs.hlsl
const uint8_t edram_load_depth_float24and32_cs[] = {
0x44, 0x58, 0x42, 0x43, 0xF3, 0xA3, 0xA4, 0x14, 0x0A, 0x50, 0x56, 0x49,
0x5D, 0x09, 0x6C, 0xBF, 0x33, 0xC9, 0xC1, 0x9A, 0x01, 0x00, 0x00, 0x00,
0xAC, 0x0D, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00,
0x10, 0x0D, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00,
0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x6F, 0x61,
0x64, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x5F, 0x73, 0x6F, 0x75, 0x72,
0x63, 0x65, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F,
0x6C, 0x6F, 0x61, 0x64, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x5F, 0x64,
0x65, 0x73, 0x74, 0x00, 0x58, 0x65, 0x45, 0x64, 0x72, 0x61, 0x6D, 0x4C,
0x6F, 0x61, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x65, 0x43, 0x6F, 0x6E, 0x73,
0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0xAB, 0xAB, 0xE8, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x30, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x83, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D,
0x5F, 0x72, 0x74, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x5F, 0x64, 0x65,
0x70, 0x74, 0x68, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x64,
0x77, 0x6F, 0x72, 0x64, 0x00, 0xAB, 0xAB, 0xAB, 0x00, 0x00, 0x13, 0x00,
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x65,
0x64, 0x72, 0x61, 0x6D, 0x5F, 0x72, 0x74, 0x5F, 0x63, 0x6F, 0x6C, 0x6F,
0x72, 0x5F, 0x64, 0x65, 0x70, 0x74, 0x68, 0x5F, 0x70, 0x69, 0x74, 0x63,
0x68, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x72,
0x74, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x6F, 0x66,
0x66, 0x73, 0x65, 0x74, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61,
0x6D, 0x5F, 0x72, 0x74, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C,
0x5F, 0x70, 0x69, 0x74, 0x63, 0x68, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64,
0x72, 0x61, 0x6D, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x5F, 0x73, 0x61, 0x6D,
0x70, 0x6C, 0x65, 0x73, 0x5F, 0x32, 0x78, 0x5F, 0x64, 0x65, 0x70, 0x74,
0x68, 0x5F, 0x70, 0x69, 0x74, 0x63, 0x68, 0x00, 0x4D, 0x69, 0x63, 0x72,
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C,
0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F,
0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2E, 0x31, 0x00,
0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58,
0xDC, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x77, 0x02, 0x00, 0x00,
0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06,
0x46, 0x7E, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x06,
0x46, 0xEE, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x02,
0x32, 0x10, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x02, 0x32, 0x20, 0x02, 0x00,
0x5F, 0x00, 0x00, 0x02, 0x32, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02,
0x07, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x06,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00,
0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C,
0x62, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x04, 0x03,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x06,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x06,
0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A,
0xA2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0D, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF,
0x1E, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01,
0x55, 0x00, 0x00, 0x09, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x08, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x10, 0x02, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x10, 0x02, 0x00, 0x26, 0x00, 0x00, 0x07,
0x00, 0xD0, 0x00, 0x00, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
0x23, 0x00, 0x00, 0x09, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x00, 0x14, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0B,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
0x0A, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x00, 0x00, 0xA0, 0x00, 0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x7E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x05, 0xF2, 0x00, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF,
0xF5, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, 0x0C, 0xF2, 0x00, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x37, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0x37, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x37, 0x00, 0x00, 0x0C, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0x7F, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F,
0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x8C, 0x00, 0x00, 0x14,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B,
0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x4F, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38,
0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8,
0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x06, 0x00, 0x02, 0x00, 0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x0A, 0x32, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x56, 0x05, 0x02, 0x00, 0xD6, 0x85, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x86, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08, 0xF2, 0xE0, 0x21, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x14, 0xE2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x56, 0x0E, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE6, 0x0A, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08,
0x12, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1F, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
};

View File

@ -0,0 +1,117 @@
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeEdramLoadStoreConstants
// {
//
// uint xe_edram_rt_color_depth_offset;// Offset: 0 Size: 4
// uint xe_edram_rt_color_depth_pitch;// Offset: 4 Size: 4
// uint xe_edram_rt_stencil_offset; // Offset: 8 Size: 4
// uint xe_edram_rt_stencil_pitch; // Offset: 12 Size: 4
// uint xe_edram_base_samples_2x_depth_pitch;// Offset: 16 Size: 4
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_edram_load_store_source texture byte r/o T0 t0 1
// xe_edram_load_store_dest UAV byte r/w U0 u0 1
// XeEdramLoadStoreConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0
dcl_resource_raw T0[0:0], space=0
dcl_uav_raw U0[0:0], space=0
dcl_input vThreadGroupID.xy
dcl_input vThreadIDInGroup.xy
dcl_input vThreadID.xy
dcl_temps 7
dcl_thread_group 20, 16, 1
ishl r0.x, vThreadIDInGroup.x, l(2)
and r0.yz, CB0[0][1].xxxx, l(0, 0x00008000, 2047, 0)
if_nz r0.y
ult r0.y, vThreadIDInGroup.x, l(10)
uge r0.w, vThreadIDInGroup.x, l(10)
and r0.yw, r0.yyyw, l(0, 40, 0, -40)
iadd r0.y, r0.w, r0.y
iadd r0.x, r0.y, r0.x
endif
ushr r0.y, CB0[0][1].x, l(16)
imad r0.y, vThreadGroupID.y, r0.y, r0.z
iadd r0.y, r0.y, vThreadGroupID.x
imul null, r0.z, vThreadIDInGroup.y, l(320)
imad r0.y, r0.y, l(5120), r0.z
ishl r0.x, r0.x, l(2)
iadd r0.x, r0.x, r0.y
ubfe r0.y, l(1), l(13), CB0[0][1].x
ishl r0.y, r0.y, l(1)
ishl r0.x, r0.x, r0.y
ld_raw r1.xyzw, r0.x, T0[0].xyzw
ushr r2.xyzw, r1.xyzw, l(8, 8, 8, 8)
iadd r0.x, r0.x, l(0x00a00000)
ld_raw r0.xyzw, r0.x, T0[0].xyzw
ubfe r3.xyzw, l(20, 20, 20, 20), l(8, 8, 8, 8), r1.xyzw
ushr r4.xyzw, r2.xyzw, l(20, 20, 20, 20)
firstbit_hi r5.xyzw, r3.xyzw
iadd r5.xyzw, r5.xyzw, l(-11, -11, -11, -11)
movc r5.xyzw, r3.xyzw, r5.xyzw, l(21,21,21,21)
iadd r6.xyzw, -r5.xyzw, l(1, 1, 1, 1)
movc r6.xyzw, r4.xyzw, r4.xyzw, r6.xyzw
ishl r5.xyzw, r3.xyzw, r5.xyzw
and r5.xyzw, r5.xyzw, l(0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff)
movc r3.xyzw, r4.xyzw, r3.xyzw, r5.xyzw
ishl r4.xyzw, r6.xyzw, l(23, 23, 23, 23)
iadd r4.xyzw, r4.xyzw, l(0x38000000, 0x38000000, 0x38000000, 0x38000000)
ishl r3.xyzw, r3.xyzw, l(3, 3, 3, 3)
iadd r3.xyzw, r4.xyzw, r3.xyzw
movc r3.xyzw, r2.xyzw, r3.xyzw, l(0,0,0,0)
iadd r4.xyzw, r0.xyzw, -r3.xyzw
uge r5.xyzw, l(0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), r0.xyzw
and r0.xyzw, r0.xyzw, r5.xyzw
umin r0.xyzw, r0.xyzw, l(0x3ffffff8, 0x3ffffff8, 0x3ffffff8, 0x3ffffff8)
bfi r5.xyzw, l(23, 23, 23, 23), l(0, 0, 0, 0), r0.xyzw, l(0x00800000, 0x00800000, 0x00800000, 0x00800000)
ushr r6.xyzw, r0.xyzw, l(23, 23, 23, 23)
iadd r6.xyzw, -r6.xyzw, l(113, 113, 113, 113)
umin r6.xyzw, r6.xyzw, l(24, 24, 24, 24)
ushr r5.xyzw, r5.xyzw, r6.xyzw
ult r6.xyzw, r0.xyzw, l(0x38800000, 0x38800000, 0x38800000, 0x38800000)
iadd r0.xyzw, r0.xyzw, l(0xc8000000, 0xc8000000, 0xc8000000, 0xc8000000)
movc r0.xyzw, r6.xyzw, r5.xyzw, r0.xyzw
iadd r5.xyzw, r0.xyzw, l(3, 3, 3, 3)
ubfe r0.xyzw, l(1, 1, 1, 1), l(3, 3, 3, 3), r0.xyzw
iadd r0.xyzw, r0.xyzw, r5.xyzw
ubfe r0.xyzw, l(24, 24, 24, 24), l(3, 3, 3, 3), r0.xyzw
ieq r0.xyzw, r2.xyzw, r0.xyzw
and r0.xyzw, r0.xyzw, l(1, 1, 1, 1)
imad r0.xyzw, r4.xyzw, r0.xyzw, r3.xyzw
ishl r2.xy, vThreadID.xxxx, l(4, 2, 0, 0)
imad r2.xy, vThreadID.yyyy, CB0[0][0].ywyy, r2.xyxx
iadd r2.xy, r2.xyxx, CB0[0][0].xzxx
store_raw U0[0].xyzw, r2.x, r0.xyzw
and r0.x, r1.x, l(255)
bfi r0.yzw, l(0, 8, 8, 8), l(0, 8, 16, 24), r1.yyzw, l(0, 0, 0, 0)
iadd r0.xy, r0.zwzz, r0.xyxx
iadd r0.x, r0.y, r0.x
store_raw U0[0].x, r2.y, r0.x
ret
// Approximately 67 instruction slots used

View File

@ -1,11 +1,11 @@
// generated from `xb buildhlsl` // generated from `xb buildhlsl`
// source: edram_load_depth_float.cs.hlsl // source: edram_load_depth_float.cs.hlsl
const uint8_t edram_load_depth_float_cs[] = { const uint8_t edram_load_depth_float_cs[] = {
0x44, 0x58, 0x42, 0x43, 0xF3, 0xA3, 0xA4, 0x14, 0x0A, 0x50, 0x56, 0x49, 0x44, 0x58, 0x42, 0x43, 0x17, 0xEE, 0x03, 0x06, 0xD3, 0x6E, 0x58, 0x75,
0x5D, 0x09, 0x6C, 0xBF, 0x33, 0xC9, 0xC1, 0x9A, 0x01, 0x00, 0x00, 0x00, 0x66, 0x3B, 0x5B, 0x87, 0x2F, 0xF9, 0x44, 0x9E, 0x01, 0x00, 0x00, 0x00,
0xAC, 0x0D, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x64, 0x0A, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00,
0x10, 0x0D, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00, 0xC8, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00,
0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00, 0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
@ -69,7 +69,7 @@ const uint8_t edram_load_depth_float_cs[] = {
0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58,
0xDC, 0x09, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x77, 0x02, 0x00, 0x00, 0x94, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0xA5, 0x01, 0x00, 0x00,
0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00, 0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06,
@ -126,168 +126,98 @@ const uint8_t edram_load_depth_float_cs[] = {
0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x20, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x0A,
0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x56, 0x05, 0x02, 0x00,
0xD6, 0x85, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x86, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x00, 0x00, 0xA0, 0x00, 0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x7E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x14, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x05, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0x02, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0xF5, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, 0x0C, 0xF2, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x05,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x37, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0x02, 0x40, 0x00, 0x00, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0x37, 0x00, 0x00, 0x09, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x00, 0x0C,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x0A, 0x02, 0x40, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B,
0x06, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x37, 0x00, 0x00, 0x0C, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0x7F, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F,
0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x8C, 0x00, 0x00, 0x14,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B,
0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80, 0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x4F, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38,
0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8,
0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x05, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00,
0x06, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00,
0x29, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x06, 0x00, 0x02, 0x00, 0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x23, 0x00, 0x00, 0x0A, 0x32, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
0x56, 0x05, 0x02, 0x00, 0xD6, 0x85, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x37, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00,
0x86, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x29, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x0C, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08, 0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08, 0xF2, 0xE0, 0x21, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x14, 0xE2, 0x00, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x14, 0xE2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x56, 0x0E, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x56, 0x0E, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE6, 0x0A, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0xE6, 0x0A, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08,
0x12, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1F, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -66,11 +66,12 @@ iadd r0.x, r0.x, r0.y
ubfe r0.y, l(1), l(13), CB0[0][1].x ubfe r0.y, l(1), l(13), CB0[0][1].x
ishl r0.y, r0.y, l(1) ishl r0.y, r0.y, l(1)
ishl r0.x, r0.x, r0.y ishl r0.x, r0.x, r0.y
ld_raw r1.xyzw, r0.x, T0[0].xyzw
ushr r2.xyzw, r1.xyzw, l(8, 8, 8, 8)
iadd r0.x, r0.x, l(0x00a00000)
ld_raw r0.xyzw, r0.x, T0[0].xyzw ld_raw r0.xyzw, r0.x, T0[0].xyzw
ubfe r3.xyzw, l(20, 20, 20, 20), l(8, 8, 8, 8), r1.xyzw ishl r1.xy, vThreadID.xxxx, l(4, 2, 0, 0)
imad r1.xy, vThreadID.yyyy, CB0[0][0].ywyy, r1.xyxx
iadd r1.xy, r1.xyxx, CB0[0][0].xzxx
ushr r2.xyzw, r0.xyzw, l(8, 8, 8, 8)
ubfe r3.xyzw, l(20, 20, 20, 20), l(8, 8, 8, 8), r0.xyzw
ushr r4.xyzw, r2.xyzw, l(20, 20, 20, 20) ushr r4.xyzw, r2.xyzw, l(20, 20, 20, 20)
firstbit_hi r5.xyzw, r3.xyzw firstbit_hi r5.xyzw, r3.xyzw
iadd r5.xyzw, r5.xyzw, l(-11, -11, -11, -11) iadd r5.xyzw, r5.xyzw, l(-11, -11, -11, -11)
@ -84,34 +85,12 @@ ishl r4.xyzw, r6.xyzw, l(23, 23, 23, 23)
iadd r4.xyzw, r4.xyzw, l(0x38000000, 0x38000000, 0x38000000, 0x38000000) iadd r4.xyzw, r4.xyzw, l(0x38000000, 0x38000000, 0x38000000, 0x38000000)
ishl r3.xyzw, r3.xyzw, l(3, 3, 3, 3) ishl r3.xyzw, r3.xyzw, l(3, 3, 3, 3)
iadd r3.xyzw, r4.xyzw, r3.xyzw iadd r3.xyzw, r4.xyzw, r3.xyzw
movc r3.xyzw, r2.xyzw, r3.xyzw, l(0,0,0,0) movc r2.xyzw, r2.xyzw, r3.xyzw, l(0,0,0,0)
iadd r4.xyzw, r0.xyzw, -r3.xyzw store_raw U0[0].xyzw, r1.x, r2.xyzw
uge r5.xyzw, l(0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), r0.xyzw and r2.x, r0.x, l(255)
and r0.xyzw, r0.xyzw, r5.xyzw bfi r2.yzw, l(0, 8, 8, 8), l(0, 8, 16, 24), r0.yyzw, l(0, 0, 0, 0)
umin r0.xyzw, r0.xyzw, l(0x3ffffff8, 0x3ffffff8, 0x3ffffff8, 0x3ffffff8) iadd r0.xy, r2.zwzz, r2.xyxx
bfi r5.xyzw, l(23, 23, 23, 23), l(0, 0, 0, 0), r0.xyzw, l(0x00800000, 0x00800000, 0x00800000, 0x00800000)
ushr r6.xyzw, r0.xyzw, l(23, 23, 23, 23)
iadd r6.xyzw, -r6.xyzw, l(113, 113, 113, 113)
umin r6.xyzw, r6.xyzw, l(24, 24, 24, 24)
ushr r5.xyzw, r5.xyzw, r6.xyzw
ult r6.xyzw, r0.xyzw, l(0x38800000, 0x38800000, 0x38800000, 0x38800000)
iadd r0.xyzw, r0.xyzw, l(0xc8000000, 0xc8000000, 0xc8000000, 0xc8000000)
movc r0.xyzw, r6.xyzw, r5.xyzw, r0.xyzw
iadd r5.xyzw, r0.xyzw, l(3, 3, 3, 3)
ubfe r0.xyzw, l(1, 1, 1, 1), l(3, 3, 3, 3), r0.xyzw
iadd r0.xyzw, r0.xyzw, r5.xyzw
ubfe r0.xyzw, l(24, 24, 24, 24), l(3, 3, 3, 3), r0.xyzw
ieq r0.xyzw, r2.xyzw, r0.xyzw
and r0.xyzw, r0.xyzw, l(1, 1, 1, 1)
imad r0.xyzw, r4.xyzw, r0.xyzw, r3.xyzw
ishl r2.xy, vThreadID.xxxx, l(4, 2, 0, 0)
imad r2.xy, vThreadID.yyyy, CB0[0][0].ywyy, r2.xyxx
iadd r2.xy, r2.xyxx, CB0[0][0].xzxx
store_raw U0[0].xyzw, r2.x, r0.xyzw
and r0.x, r1.x, l(255)
bfi r0.yzw, l(0, 8, 8, 8), l(0, 8, 16, 24), r1.yyzw, l(0, 0, 0, 0)
iadd r0.xy, r0.zwzz, r0.xyxx
iadd r0.x, r0.y, r0.x iadd r0.x, r0.y, r0.x
store_raw U0[0].x, r2.y, r0.x store_raw U0[0].x, r1.y, r0.x
ret ret
// Approximately 67 instruction slots used // Approximately 46 instruction slots used

View File

@ -0,0 +1,226 @@
// generated from `xb buildhlsl`
// source: edram_store_depth_float24and32.cs.hlsl
const uint8_t edram_store_depth_float24and32_cs[] = {
0x44, 0x58, 0x42, 0x43, 0xC6, 0x10, 0x80, 0x14, 0x97, 0x01, 0xE4, 0x46,
0x76, 0xF1, 0x67, 0xD3, 0xDF, 0x50, 0x25, 0xF7, 0x01, 0x00, 0x00, 0x00,
0x64, 0x0A, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00,
0xC8, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00,
0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x6F, 0x61,
0x64, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x5F, 0x73, 0x6F, 0x75, 0x72,
0x63, 0x65, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F,
0x6C, 0x6F, 0x61, 0x64, 0x5F, 0x73, 0x74, 0x6F, 0x72, 0x65, 0x5F, 0x64,
0x65, 0x73, 0x74, 0x00, 0x58, 0x65, 0x45, 0x64, 0x72, 0x61, 0x6D, 0x4C,
0x6F, 0x61, 0x64, 0x53, 0x74, 0x6F, 0x72, 0x65, 0x43, 0x6F, 0x6E, 0x73,
0x74, 0x61, 0x6E, 0x74, 0x73, 0x00, 0xAB, 0xAB, 0xE8, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x1C, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x30, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x83, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D,
0x5F, 0x72, 0x74, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x5F, 0x64, 0x65,
0x70, 0x74, 0x68, 0x5F, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x64,
0x77, 0x6F, 0x72, 0x64, 0x00, 0xAB, 0xAB, 0xAB, 0x00, 0x00, 0x13, 0x00,
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x65,
0x64, 0x72, 0x61, 0x6D, 0x5F, 0x72, 0x74, 0x5F, 0x63, 0x6F, 0x6C, 0x6F,
0x72, 0x5F, 0x64, 0x65, 0x70, 0x74, 0x68, 0x5F, 0x70, 0x69, 0x74, 0x63,
0x68, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x72,
0x74, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C, 0x5F, 0x6F, 0x66,
0x66, 0x73, 0x65, 0x74, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64, 0x72, 0x61,
0x6D, 0x5F, 0x72, 0x74, 0x5F, 0x73, 0x74, 0x65, 0x6E, 0x63, 0x69, 0x6C,
0x5F, 0x70, 0x69, 0x74, 0x63, 0x68, 0x00, 0x78, 0x65, 0x5F, 0x65, 0x64,
0x72, 0x61, 0x6D, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x5F, 0x73, 0x61, 0x6D,
0x70, 0x6C, 0x65, 0x73, 0x5F, 0x32, 0x78, 0x5F, 0x64, 0x65, 0x70, 0x74,
0x68, 0x5F, 0x70, 0x69, 0x74, 0x63, 0x68, 0x00, 0x4D, 0x69, 0x63, 0x72,
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C,
0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F,
0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2E, 0x31, 0x00,
0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58,
0x94, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0xA5, 0x01, 0x00, 0x00,
0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06,
0x46, 0x7E, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x00, 0x00, 0x06,
0x46, 0xEE, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x02,
0x32, 0x10, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x02, 0x32, 0x20, 0x02, 0x00,
0x5F, 0x00, 0x00, 0x02, 0x32, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02,
0x05, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x09,
0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x0A,
0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x05, 0x02, 0x00,
0xD6, 0x85, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x09, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xA5, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0x7F, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F,
0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x8C, 0x00, 0x00, 0x14,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B,
0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x4F, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38,
0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8,
0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x08,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x70, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xE2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x11,
0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x62, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x06, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x04, 0x03, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A, 0xA2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x56, 0x0D, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x07,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x09,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x08,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x10, 0x02, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0A, 0x10, 0x02, 0x00, 0x26, 0x00, 0x00, 0x07, 0x00, 0xD0, 0x00, 0x00,
0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x20, 0x02, 0x00,
0x01, 0x40, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x09,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07,
0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0B, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08,
0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0xA6, 0x00, 0x00, 0x08,
0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
};

View File

@ -0,0 +1,95 @@
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions:
//
// cbuffer XeEdramLoadStoreConstants
// {
//
// uint xe_edram_rt_color_depth_offset;// Offset: 0 Size: 4
// uint xe_edram_rt_color_depth_pitch;// Offset: 4 Size: 4
// uint xe_edram_rt_stencil_offset; // Offset: 8 Size: 4
// uint xe_edram_rt_stencil_pitch; // Offset: 12 Size: 4
// uint xe_edram_base_samples_2x_depth_pitch;// Offset: 16 Size: 4
//
// }
//
//
// Resource Bindings:
//
// Name Type Format Dim ID HLSL Bind Count
// ------------------------------ ---------- ------- ----------- ------- -------------- ------
// xe_edram_load_store_source texture byte r/o T0 t0 1
// xe_edram_load_store_dest UAV byte r/w U0 u0 1
// XeEdramLoadStoreConstants cbuffer NA NA CB0 cb0 1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][2], immediateIndexed, space=0
dcl_resource_raw T0[0:0], space=0
dcl_uav_raw U0[0:0], space=0
dcl_input vThreadGroupID.xy
dcl_input vThreadIDInGroup.xy
dcl_input vThreadID.xy
dcl_temps 5
dcl_thread_group 20, 16, 1
ishl r0.xy, vThreadID.xxxx, l(4, 2, 0, 0)
imad r0.xy, vThreadID.yyyy, CB0[0][0].ywyy, r0.xyxx
iadd r0.xy, r0.xyxx, CB0[0][0].xzxx
ld_raw r1.xyzw, r0.x, T0[0].xyzw
uge r2.xyzw, l(0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), r1.xyzw
and r2.xyzw, r1.xyzw, r2.xyzw
umin r2.xyzw, r2.xyzw, l(0x3ffffff8, 0x3ffffff8, 0x3ffffff8, 0x3ffffff8)
bfi r3.xyzw, l(23, 23, 23, 23), l(0, 0, 0, 0), r2.xyzw, l(0x00800000, 0x00800000, 0x00800000, 0x00800000)
ushr r4.xyzw, r2.xyzw, l(23, 23, 23, 23)
iadd r4.xyzw, -r4.xyzw, l(113, 113, 113, 113)
umin r4.xyzw, r4.xyzw, l(24, 24, 24, 24)
ushr r3.xyzw, r3.xyzw, r4.xyzw
ult r4.xyzw, r2.xyzw, l(0x38800000, 0x38800000, 0x38800000, 0x38800000)
iadd r2.xyzw, r2.xyzw, l(0xc8000000, 0xc8000000, 0xc8000000, 0xc8000000)
movc r2.xyzw, r4.xyzw, r3.xyzw, r2.xyzw
iadd r3.xyzw, r2.xyzw, l(3, 3, 3, 3)
ubfe r2.xyzw, l(1, 1, 1, 1), l(3, 3, 3, 3), r2.xyzw
iadd r2.xyzw, r2.xyzw, r3.xyzw
ushr r2.xyzw, r2.xyzw, l(3, 3, 3, 3)
ld_raw r0.x, r0.y, T0[0].xxxx
ushr r0.yzw, r0.xxxx, l(0, 8, 16, 24)
bfi r0.xyzw, l(24, 24, 24, 24), l(8, 8, 8, 8), r2.xyzw, r0.xyzw
ishl r2.x, vThreadIDInGroup.x, l(2)
and r2.yz, CB0[0][1].xxxx, l(0, 0x00008000, 2047, 0)
if_nz r2.y
ult r2.y, vThreadIDInGroup.x, l(10)
uge r2.w, vThreadIDInGroup.x, l(10)
and r2.yw, r2.yyyw, l(0, 40, 0, -40)
iadd r2.y, r2.w, r2.y
iadd r2.x, r2.y, r2.x
endif
ushr r2.y, CB0[0][1].x, l(16)
imad r2.y, vThreadGroupID.y, r2.y, r2.z
iadd r2.y, r2.y, vThreadGroupID.x
imul null, r2.z, vThreadIDInGroup.y, l(320)
imad r2.y, r2.y, l(5120), r2.z
ishl r2.x, r2.x, l(2)
iadd r2.x, r2.x, r2.y
ubfe r2.y, l(1), l(13), CB0[0][1].x
ishl r2.y, r2.y, l(1)
ishl r2.x, r2.x, r2.y
store_raw U0[0].xyzw, r2.x, r0.xyzw
iadd r0.x, r2.x, l(0x00a00000)
store_raw U0[0].xyzw, r0.x, r1.xyzw
ret
// Approximately 45 instruction slots used

View File

@ -1,11 +1,11 @@
// generated from `xb buildhlsl` // generated from `xb buildhlsl`
// source: edram_store_depth_float.cs.hlsl // source: edram_store_depth_float.cs.hlsl
const uint8_t edram_store_depth_float_cs[] = { const uint8_t edram_store_depth_float_cs[] = {
0x44, 0x58, 0x42, 0x43, 0xC6, 0x10, 0x80, 0x14, 0x97, 0x01, 0xE4, 0x46, 0x44, 0x58, 0x42, 0x43, 0xF1, 0x72, 0x64, 0x54, 0x9D, 0xF6, 0x79, 0x48,
0x76, 0xF1, 0x67, 0xD3, 0xDF, 0x50, 0x25, 0xF7, 0x01, 0x00, 0x00, 0x00, 0x2F, 0x8C, 0xD1, 0x59, 0x56, 0x1C, 0x90, 0x9A, 0x01, 0x00, 0x00, 0x00,
0x64, 0x0A, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x28, 0x0A, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x2C, 0x03, 0x00, 0x00,
0xC8, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00, 0x8C, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD0, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0x53, 0x43, 0x00, 0x05, 0x00, 0x00,
0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00, 0xA8, 0x02, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
@ -69,7 +69,7 @@ const uint8_t edram_store_depth_float_cs[] = {
0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x48, 0x45, 0x58,
0x94, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0xA5, 0x01, 0x00, 0x00, 0x58, 0x06, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x96, 0x01, 0x00, 0x00,
0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00, 0x6A, 0x08, 0x00, 0x01, 0x59, 0x00, 0x00, 0x07, 0x46, 0x8E, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x06,
@ -79,7 +79,7 @@ const uint8_t edram_store_depth_float_cs[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x02,
0x32, 0x10, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x02, 0x32, 0x20, 0x02, 0x00, 0x32, 0x10, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x02, 0x32, 0x20, 0x02, 0x00,
0x5F, 0x00, 0x00, 0x02, 0x32, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02, 0x5F, 0x00, 0x00, 0x02, 0x32, 0x00, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02,
0x05, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9B, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x09,
0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
@ -96,53 +96,53 @@ const uint8_t edram_store_depth_float_cs[] = {
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0x7F, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x02, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F,
0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x8C, 0x00, 0x00, 0x14, 0xF8, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x3F, 0x8C, 0x00, 0x00, 0x14,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B, 0x17, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0B,
0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x07, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x07,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x4F, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38, 0x00, 0x00, 0x80, 0x38,
0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8,
0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x00, 0x00, 0x09,
0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x04, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0A,
0xF2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0F, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0xF2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x03, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00, 0x08,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
@ -155,64 +155,59 @@ const uint8_t edram_store_depth_float_cs[] = {
0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x46, 0x0E, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x62, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x62, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x06, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x04, 0x03, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x04, 0x03, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x20, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A, 0xA2, 0x00, 0x10, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0A, 0xA2, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x56, 0x0D, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x56, 0x0D, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xFF, 0xFF, 0x1E, 0x00, 0x00, 0x07,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x09,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x08, 0x01, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x08,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x10, 0x02, 0x00, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x10, 0x02, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0A, 0x10, 0x02, 0x00, 0x26, 0x00, 0x00, 0x07, 0x00, 0xD0, 0x00, 0x00, 0x0A, 0x10, 0x02, 0x00, 0x26, 0x00, 0x00, 0x07, 0x00, 0xD0, 0x00, 0x00,
0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x20, 0x02, 0x00, 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x20, 0x02, 0x00,
0x01, 0x40, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x09, 0x01, 0x40, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x09,
0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x2A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07,
0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0B, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x0B, 0x22, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x30, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08, 0x1A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA6, 0x00, 0x00, 0x08,
0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0xA6, 0x00, 0x00, 0x08,
0xF2, 0xE0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -222,5 +217,5 @@ const uint8_t edram_store_depth_float_cs[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
}; };

View File

@ -45,51 +45,49 @@ dcl_uav_raw U0[0:0], space=0
dcl_input vThreadGroupID.xy dcl_input vThreadGroupID.xy
dcl_input vThreadIDInGroup.xy dcl_input vThreadIDInGroup.xy
dcl_input vThreadID.xy dcl_input vThreadID.xy
dcl_temps 5 dcl_temps 4
dcl_thread_group 20, 16, 1 dcl_thread_group 20, 16, 1
ishl r0.xy, vThreadID.xxxx, l(4, 2, 0, 0) ishl r0.xy, vThreadID.xxxx, l(4, 2, 0, 0)
imad r0.xy, vThreadID.yyyy, CB0[0][0].ywyy, r0.xyxx imad r0.xy, vThreadID.yyyy, CB0[0][0].ywyy, r0.xyxx
iadd r0.xy, r0.xyxx, CB0[0][0].xzxx iadd r0.xy, r0.xyxx, CB0[0][0].xzxx
ld_raw r1.xyzw, r0.x, T0[0].xyzw ld_raw r1.xyzw, r0.x, T0[0].xyzw
uge r2.xyzw, l(0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), r1.xyzw uge r2.xyzw, l(0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), r1.xyzw
and r2.xyzw, r1.xyzw, r2.xyzw and r1.xyzw, r1.xyzw, r2.xyzw
umin r2.xyzw, r2.xyzw, l(0x3ffffff8, 0x3ffffff8, 0x3ffffff8, 0x3ffffff8) umin r1.xyzw, r1.xyzw, l(0x3ffffff8, 0x3ffffff8, 0x3ffffff8, 0x3ffffff8)
bfi r3.xyzw, l(23, 23, 23, 23), l(0, 0, 0, 0), r2.xyzw, l(0x00800000, 0x00800000, 0x00800000, 0x00800000) bfi r2.xyzw, l(23, 23, 23, 23), l(0, 0, 0, 0), r1.xyzw, l(0x00800000, 0x00800000, 0x00800000, 0x00800000)
ushr r4.xyzw, r2.xyzw, l(23, 23, 23, 23) ushr r3.xyzw, r1.xyzw, l(23, 23, 23, 23)
iadd r4.xyzw, -r4.xyzw, l(113, 113, 113, 113) iadd r3.xyzw, -r3.xyzw, l(113, 113, 113, 113)
umin r4.xyzw, r4.xyzw, l(24, 24, 24, 24) umin r3.xyzw, r3.xyzw, l(24, 24, 24, 24)
ushr r3.xyzw, r3.xyzw, r4.xyzw ushr r2.xyzw, r2.xyzw, r3.xyzw
ult r4.xyzw, r2.xyzw, l(0x38800000, 0x38800000, 0x38800000, 0x38800000) ult r3.xyzw, r1.xyzw, l(0x38800000, 0x38800000, 0x38800000, 0x38800000)
iadd r2.xyzw, r2.xyzw, l(0xc8000000, 0xc8000000, 0xc8000000, 0xc8000000) iadd r1.xyzw, r1.xyzw, l(0xc8000000, 0xc8000000, 0xc8000000, 0xc8000000)
movc r2.xyzw, r4.xyzw, r3.xyzw, r2.xyzw movc r1.xyzw, r3.xyzw, r2.xyzw, r1.xyzw
iadd r3.xyzw, r2.xyzw, l(3, 3, 3, 3) iadd r2.xyzw, r1.xyzw, l(3, 3, 3, 3)
ubfe r2.xyzw, l(1, 1, 1, 1), l(3, 3, 3, 3), r2.xyzw ubfe r1.xyzw, l(1, 1, 1, 1), l(3, 3, 3, 3), r1.xyzw
iadd r2.xyzw, r2.xyzw, r3.xyzw iadd r1.xyzw, r1.xyzw, r2.xyzw
ushr r2.xyzw, r2.xyzw, l(3, 3, 3, 3) ushr r1.xyzw, r1.xyzw, l(3, 3, 3, 3)
ld_raw r0.x, r0.y, T0[0].xxxx ld_raw r0.x, r0.y, T0[0].xxxx
ushr r0.yzw, r0.xxxx, l(0, 8, 16, 24) ushr r0.yzw, r0.xxxx, l(0, 8, 16, 24)
bfi r0.xyzw, l(24, 24, 24, 24), l(8, 8, 8, 8), r2.xyzw, r0.xyzw bfi r0.xyzw, l(24, 24, 24, 24), l(8, 8, 8, 8), r1.xyzw, r0.xyzw
ishl r2.x, vThreadIDInGroup.x, l(2) ishl r1.x, vThreadIDInGroup.x, l(2)
and r2.yz, CB0[0][1].xxxx, l(0, 0x00008000, 2047, 0) and r1.yz, CB0[0][1].xxxx, l(0, 0x00008000, 2047, 0)
if_nz r2.y if_nz r1.y
ult r2.y, vThreadIDInGroup.x, l(10) ult r1.y, vThreadIDInGroup.x, l(10)
uge r2.w, vThreadIDInGroup.x, l(10) uge r1.w, vThreadIDInGroup.x, l(10)
and r2.yw, r2.yyyw, l(0, 40, 0, -40) and r1.yw, r1.yyyw, l(0, 40, 0, -40)
iadd r2.y, r2.w, r2.y iadd r1.y, r1.w, r1.y
iadd r2.x, r2.y, r2.x iadd r1.x, r1.y, r1.x
endif endif
ushr r2.y, CB0[0][1].x, l(16) ushr r1.y, CB0[0][1].x, l(16)
imad r2.y, vThreadGroupID.y, r2.y, r2.z imad r1.y, vThreadGroupID.y, r1.y, r1.z
iadd r2.y, r2.y, vThreadGroupID.x iadd r1.y, r1.y, vThreadGroupID.x
imul null, r2.z, vThreadIDInGroup.y, l(320) imul null, r1.z, vThreadIDInGroup.y, l(320)
imad r2.y, r2.y, l(5120), r2.z imad r1.y, r1.y, l(5120), r1.z
ishl r2.x, r2.x, l(2) ishl r1.x, r1.x, l(2)
iadd r2.x, r2.x, r2.y iadd r1.x, r1.x, r1.y
ubfe r2.y, l(1), l(13), CB0[0][1].x ubfe r1.y, l(1), l(13), CB0[0][1].x
ishl r2.y, r2.y, l(1) ishl r1.y, r1.y, l(1)
ishl r2.x, r2.x, r2.y ishl r1.x, r1.x, r1.y
store_raw U0[0].xyzw, r2.x, r0.xyzw store_raw U0[0].xyzw, r1.x, r0.xyzw
iadd r0.x, r2.x, l(0x00a00000)
store_raw U0[0].xyzw, r0.x, r1.xyzw
ret ret
// Approximately 45 instruction slots used // Approximately 43 instruction slots used

Binary file not shown.

View File

@ -0,0 +1,156 @@
// generated from `xb buildhlsl`
// source: float24_round.ps.hlsl
const uint8_t float24_round_ps[] = {
0x44, 0x58, 0x42, 0x43, 0xDF, 0x71, 0xF3, 0x0A, 0x4A, 0xDB, 0xC3, 0x80,
0x1E, 0xE4, 0x39, 0x21, 0x59, 0x07, 0x78, 0x97, 0x01, 0x00, 0x00, 0x00,
0x18, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0xA0, 0x00, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0xC4, 0x02, 0x00, 0x00,
0x7C, 0x06, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x64, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0xFF, 0xFF, 0x00, 0x05, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52,
0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65,
0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31,
0x30, 0x2E, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4E, 0xE8, 0x01, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD9, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
0x4F, 0x4F, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5F, 0x50, 0x6F, 0x73, 0x69,
0x74, 0x69, 0x6F, 0x6E, 0x00, 0xAB, 0xAB, 0xAB, 0x4F, 0x53, 0x47, 0x4E,
0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x0E, 0x00, 0x00,
0x53, 0x56, 0x5F, 0x44, 0x65, 0x70, 0x74, 0x68, 0x00, 0xAB, 0xAB, 0xAB,
0x53, 0x48, 0x45, 0x58, 0xB0, 0x03, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
0xEC, 0x00, 0x00, 0x00, 0x6A, 0x08, 0x00, 0x01, 0x64, 0x38, 0x00, 0x04,
0x42, 0x10, 0x10, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x65, 0x00, 0x00, 0x02, 0x01, 0xC0, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02,
0x02, 0x00, 0x00, 0x00, 0x36, 0x20, 0x08, 0x05, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2A, 0x10, 0x10, 0x00, 0x12, 0x00, 0x00, 0x00,
0x50, 0x00, 0x10, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x08, 0x07,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F,
0x8C, 0x00, 0x10, 0x0B, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x55, 0x00, 0x20, 0x07,
0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x20, 0x08, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x54, 0x00, 0x20, 0x07,
0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x55, 0x00, 0x10, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x20, 0x07, 0x42, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x38, 0x1E, 0x00, 0x08, 0x07,
0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8,
0x37, 0x00, 0x08, 0x09, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x10, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x08, 0x09, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x08, 0x07, 0x12, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x38, 0x0F,
0x72, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x40, 0x05,
0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x40, 0x07, 0x82, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0xF5, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x40, 0x09,
0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x08, 0x08,
0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x80,
0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x37, 0x00, 0x08, 0x09, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x40, 0x07, 0x82, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x07,
0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x0F, 0x00,
0x37, 0x00, 0x10, 0x09, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, 0x00, 0x20, 0x07, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x20, 0x07, 0x42, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x29, 0x00, 0x10, 0x07,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x10, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x08, 0x08, 0x01, 0xC0, 0x00, 0x00,
0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x94, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};

View File

@ -0,0 +1,74 @@
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// TEXCOORD 0 xyzw 0 NONE float
// TEXCOORD 1 xyzw 1 NONE float
// TEXCOORD 2 xyzw 2 NONE float
// TEXCOORD 3 xyzw 3 NONE float
// TEXCOORD 4 xyzw 4 NONE float
// TEXCOORD 5 xyzw 5 NONE float
// TEXCOORD 6 xyzw 6 NONE float
// TEXCOORD 7 xyzw 7 NONE float
// TEXCOORD 8 xyzw 8 NONE float
// TEXCOORD 9 xyzw 9 NONE float
// TEXCOORD 10 xyzw 10 NONE float
// TEXCOORD 11 xyzw 11 NONE float
// TEXCOORD 12 xyzw 12 NONE float
// TEXCOORD 13 xyzw 13 NONE float
// TEXCOORD 14 xyzw 14 NONE float
// TEXCOORD 15 xyzw 15 NONE float
// TEXCOORD 16 xyz 16 NONE float
// TEXCOORD 17 xy 17 NONE float
// SV_Position 0 xyzw 18 POS float z
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Depth 0 N/A oDepth DEPTH float YES
//
// Pixel Shader runs at sample frequency
//
ps_5_1
dcl_globalFlags refactoringAllowed
dcl_input_ps_siv linear noperspective sample v18.z, position
dcl_output oDepth
dcl_temps 2
mov_sat [precise(x)] r0.x, v18.z
uge [precise(y)] r0.y, l(0x7fffffff), r0.x
and [precise(x)] r0.x, r0.x, r0.y
umin [precise(x)] r0.x, r0.x, l(0x3ffffff8)
bfi [precise(y)] r0.y, l(23), l(0), r0.x, l(0x00800000)
ushr [precise(z)] r0.z, r0.x, l(23)
iadd [precise(z)] r0.z, -r0.z, l(113)
umin [precise(z)] r0.z, r0.z, l(24)
ushr [precise(y)] r0.y, r0.y, r0.z
ult [precise(z)] r0.z, r0.x, l(0x38800000)
iadd [precise(x)] r0.x, r0.x, l(0xc8000000)
movc [precise(x)] r0.x, r0.z, r0.y, r0.x
iadd [precise(y)] r0.y, r0.x, l(3)
ubfe [precise(x)] r0.x, l(1), l(3), r0.x
iadd [precise(x)] r0.x, r0.x, r0.y
ubfe [precise(xyz)] r0.xyz, l(24, 20, 4, 0), l(3, 3, 23, 0), r0.xxxx
firstbit_hi [precise(w)] r0.w, r0.y
iadd [precise(w)] r0.w, r0.w, l(-11)
movc [precise(w)] r0.w, r0.y, r0.w, l(21)
iadd [precise(x)] r1.x, -r0.w, l(1)
movc [precise(x)] r1.x, r0.z, r0.z, r1.x
ishl [precise(w)] r0.w, r0.y, r0.w
and [precise(w)] r0.w, r0.w, l(0x000fffff)
movc [precise(y)] r0.y, r0.z, r0.y, r0.w
ishl [precise(z)] r0.z, r1.x, l(23)
iadd [precise(z)] r0.z, r0.z, l(0x38000000)
ishl [precise(y)] r0.y, r0.y, l(3)
iadd [precise(y)] r0.y, r0.z, r0.y
movc [precise(x)] oDepth, r0.x, r0.y, l(0)
ret
// Approximately 30 instruction slots used

View File

@ -0,0 +1,100 @@
// generated from `xb buildhlsl`
// source: float24_truncate.ps.hlsl
const uint8_t float24_truncate_ps[] = {
0x44, 0x58, 0x42, 0x43, 0xB8, 0x51, 0x55, 0x1D, 0xF4, 0xF1, 0xC9, 0xC0,
0x0C, 0x22, 0xD3, 0x43, 0x94, 0xDF, 0x83, 0x9D, 0x01, 0x00, 0x00, 0x00,
0x7C, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
0xA0, 0x00, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0xCC, 0x02, 0x00, 0x00,
0xE0, 0x03, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x64, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x01, 0x05, 0xFF, 0xFF, 0x00, 0x05, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x00, 0x13, 0x13, 0x44, 0x25, 0x3C, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52,
0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65,
0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31,
0x30, 0x2E, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4E, 0xE8, 0x01, 0x00, 0x00,
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xD0, 0x01, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD9, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x12, 0x00, 0x00, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
0x4F, 0x4F, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5F, 0x50, 0x6F, 0x73, 0x69,
0x74, 0x69, 0x6F, 0x6E, 0x00, 0xAB, 0xAB, 0xAB, 0x4F, 0x53, 0x47, 0x4E,
0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x0E, 0x00, 0x00,
0x53, 0x56, 0x5F, 0x44, 0x65, 0x70, 0x74, 0x68, 0x4C, 0x65, 0x73, 0x73,
0x45, 0x71, 0x75, 0x61, 0x6C, 0x00, 0xAB, 0xAB, 0x53, 0x48, 0x45, 0x58,
0x0C, 0x01, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
0x6A, 0x08, 0x00, 0x01, 0x64, 0x38, 0x00, 0x04, 0x42, 0x10, 0x10, 0x00,
0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x02,
0x01, 0x70, 0x02, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00,
0x36, 0x20, 0x08, 0x05, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x10, 0x10, 0x00, 0x12, 0x00, 0x00, 0x00, 0x50, 0x00, 0x10, 0x07,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2E,
0x1F, 0x00, 0x04, 0x03, 0x1A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8A, 0x00, 0x10, 0x09, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
0x17, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x00, 0x10, 0x08, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1A, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x24, 0x00, 0x10, 0x07,
0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x8C, 0x00, 0x08, 0x0A, 0x01, 0x70, 0x02, 0x00, 0x1A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x36, 0x00, 0x08, 0x04,
0x01, 0x70, 0x02, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x00, 0x00, 0x01, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@ -0,0 +1,55 @@
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// TEXCOORD 0 xyzw 0 NONE float
// TEXCOORD 1 xyzw 1 NONE float
// TEXCOORD 2 xyzw 2 NONE float
// TEXCOORD 3 xyzw 3 NONE float
// TEXCOORD 4 xyzw 4 NONE float
// TEXCOORD 5 xyzw 5 NONE float
// TEXCOORD 6 xyzw 6 NONE float
// TEXCOORD 7 xyzw 7 NONE float
// TEXCOORD 8 xyzw 8 NONE float
// TEXCOORD 9 xyzw 9 NONE float
// TEXCOORD 10 xyzw 10 NONE float
// TEXCOORD 11 xyzw 11 NONE float
// TEXCOORD 12 xyzw 12 NONE float
// TEXCOORD 13 xyzw 13 NONE float
// TEXCOORD 14 xyzw 14 NONE float
// TEXCOORD 15 xyzw 15 NONE float
// TEXCOORD 16 xyz 16 NONE float
// TEXCOORD 17 xy 17 NONE float
// SV_Position 0 xyzw 18 POS float z
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_DepthLessEqual 0 N/A oDepthLE DEPTHLE float YES
//
// Pixel Shader runs at sample frequency
//
ps_5_1
dcl_globalFlags refactoringAllowed
dcl_input_ps_siv linear noperspective sample v18.z, position
dcl_output oDepthLE
dcl_temps 1
mov_sat [precise(x)] r0.x, v18.z
uge [precise(y)] r0.y, r0.x, l(0x2e800000)
if_nz r0.y
ubfe [precise(y)] r0.y, l(8), l(23), r0.x
iadd [precise(y)] r0.y, -r0.y, l(116)
imax [precise(y)] r0.y, r0.y, l(3)
bfi [precise(x)] oDepthLE, r0.y, l(0), l(0), r0.x
else
mov [precise(x)] oDepthLE, l(0)
endif
ret
// Approximately 11 instruction slots used

View File

@ -7,22 +7,14 @@ void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_thread_id : SV_DispatchThreadID) { uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_sample_index = xe_group_thread_id.xy; uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u; tile_sample_index.x *= 4u;
uint edram_offset = XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index); uint4 samples = xe_edram_load_store_source.Load4(
uint4 depth24_stencil = xe_edram_load_store_source.Load4(edram_offset); XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index));
uint4 depth24 = depth24_stencil >> 8u; // Depth (exact conversion ensured during drawing).
uint4 depth32 = xe_edram_load_store_source.Load4(10485760u + edram_offset);
// Depth. If the stored 32-bit depth converted to 24-bit is the same as the
// stored 24-bit depth, load the 32-bit value because it has more precision
// (and multipass rendering is possible), if it's not, convert the 24-bit
// depth because it was overwritten by aliasing.
uint4 depth24to32 = XeFloat20e4To32(depth24);
uint4 depth = depth24to32 + (depth32 - depth24to32) *
uint4(XeFloat32To20e4(depth32) == depth24);
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch + uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset; xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, depth); xe_edram_load_store_dest.Store4(rt_offset, XeFloat20e4To32(samples >> 8u));
// Stencil. // Stencil.
uint4 stencil = (depth24_stencil & 0xFFu) << uint4(0u, 8u, 16u, 24u); uint4 stencil = (samples & 0xFFu) << uint4(0u, 8u, 16u, 24u);
stencil.xy |= stencil.zw; stencil.xy |= stencil.zw;
stencil.x |= stencil.y; stencil.x |= stencil.y;
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u + rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +

View File

@ -0,0 +1,31 @@
#include "edram_load_store.hlsli"
#include "pixel_formats.hlsli"
[numthreads(20, 16, 1)]
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint edram_offset = XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index);
uint4 depth24_stencil = xe_edram_load_store_source.Load4(edram_offset);
uint4 depth24 = depth24_stencil >> 8u;
uint4 depth32 = xe_edram_load_store_source.Load4(10485760u + edram_offset);
// Depth. If the stored 32-bit depth converted to 24-bit is the same as the
// stored 24-bit depth, load the 32-bit value because it has more precision
// (and multipass rendering is possible), if it's not, convert the 24-bit
// depth because it was overwritten by aliasing.
uint4 depth24to32 = XeFloat20e4To32(depth24);
uint4 depth = depth24to32 + (depth32 - depth24to32) *
uint4(XeFloat32To20e4(depth32) == depth24);
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, depth);
// Stencil.
uint4 stencil = (depth24_stencil & 0xFFu) << uint4(0u, 8u, 16u, 24u);
stencil.xy |= stencil.zw;
stencil.x |= stencil.y;
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +
xe_edram_rt_stencil_offset;
xe_edram_load_store_dest.Store(rt_offset, stencil.x);
}

View File

@ -5,21 +5,18 @@
void main(uint3 xe_group_id : SV_GroupID, void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID, uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) { uint3 xe_thread_id : SV_DispatchThreadID) {
// Depth. // Depth (exact conversion ensured during drawing).
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch + uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset; xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 depth32 = xe_edram_load_store_source.Load4(rt_offset); uint4 samples =
uint4 depth24_stencil = XeFloat32To20e4(depth32) << 8u; XeFloat32To20e4(xe_edram_load_store_source.Load4(rt_offset)) << 8u;
// Stencil. // Stencil.
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u + rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +
xe_edram_rt_stencil_offset; xe_edram_rt_stencil_offset;
depth24_stencil |= (xe_edram_load_store_source.Load(rt_offset).xxxx >> samples |= (xe_edram_load_store_source.Load(rt_offset).xxxx >>
uint4(0u, 8u, 16u, 24u)) & 0xFFu; uint4(0u, 8u, 16u, 24u)) & 0xFFu;
uint2 tile_sample_index = xe_group_thread_id.xy; uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u; tile_sample_index.x *= 4u;
uint edram_offset = XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index); xe_edram_load_store_dest.Store4(
// Store 24-bit depth for aliasing and checking if 32-bit depth is up to date. XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index), samples);
xe_edram_load_store_dest.Store4(edram_offset, depth24_stencil);
// Store 32-bit depth so precision isn't lost when doing multipass rendering.
xe_edram_load_store_dest.Store4(10485760u + edram_offset, depth32);
} }

View File

@ -0,0 +1,25 @@
#include "edram_load_store.hlsli"
#include "pixel_formats.hlsli"
[numthreads(20, 16, 1)]
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
// Depth.
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 depth32 = xe_edram_load_store_source.Load4(rt_offset);
uint4 depth24_stencil = XeFloat32To20e4(depth32) << 8u;
// Stencil.
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +
xe_edram_rt_stencil_offset;
depth24_stencil |= (xe_edram_load_store_source.Load(rt_offset).xxxx >>
uint4(0u, 8u, 16u, 24u)) & 0xFFu;
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint edram_offset = XeEdramOffset32bpp(xe_group_id.xy, tile_sample_index);
// Store 24-bit depth for aliasing and checking if 32-bit depth is up to date.
xe_edram_load_store_dest.Store4(edram_offset, depth24_stencil);
// Store 32-bit depth so precision isn't lost when doing multipass rendering.
xe_edram_load_store_dest.Store4(10485760u + edram_offset, depth32);
}

View File

@ -7,8 +7,7 @@ void main(uint3 xe_group_id : SV_GroupID,
// Depth. // Depth.
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch + uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset; xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 samples = uint4 samples = xe_edram_load_store_source.Load4(rt_offset) << 8u;
(xe_edram_load_store_source.Load4(rt_offset) & 0xFFFFFFu) << 8u;
// Stencil. // Stencil.
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u + rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +
xe_edram_rt_stencil_offset; xe_edram_rt_stencil_offset;

View File

@ -0,0 +1,13 @@
#include "pixel_formats.hlsli"
#include "xenos_draw.hlsli"
struct XePSInput {
XeVertexPrePS pre_ps;
sample float4 position : SV_Position;
};
precise float main(XePSInput xe_input) : SV_Depth {
// Input Z may be outside the viewport range (it's clamped after the shader).
return asfloat(
XeFloat20e4To32(XeFloat32To20e4(asuint(saturate(xe_input.position.z)))));
}

View File

@ -0,0 +1,38 @@
#include "pixel_formats.hlsli"
#include "xenos_draw.hlsli"
struct XePSInput {
XeVertexPrePS pre_ps;
sample float4 position : SV_Position;
};
precise float main(XePSInput xe_input) : SV_DepthLessEqual {
// Simplified conversion, always less than or equal to the original value -
// just drop the lower bits.
// The float32 exponent bias is 127.
// After saturating, the exponent range is -127...0.
// The smallest normalized 20e4 exponent is -14 - should drop 3 mantissa bits
// at -14 or above.
// The smallest denormalized 20e4 number is -34 - should drop 23 mantissa bits
// at -34.
// Anything smaller than 2^-34 becomes 0.
// Input Z may be outside the viewport range (it's clamped after the shader).
precise uint depth = asuint(saturate(xe_input.position.z));
// Check if the number is representable as a float24 after truncation - the
// exponent is at least -34.
if (depth >= 0x2E800000u) {
// Extract the biased float32 exponent:
// 113+ at exponent -14+.
// 93 at exponent -34.
uint exponent = (depth >> 23u) & 0xFFu;
// Convert exponent to the shift amount.
// 116 - 113 = 3.
// 116 - 93 = 23.
uint shift = asuint(max(116 - asint(exponent), 3));
depth = depth >> shift << shift;
} else {
// The number is not representable as float24 after truncation - zero.
depth = 0u;
}
return asfloat(depth);
}

View File

@ -495,6 +495,16 @@ void XeR11G11B10SNormToRGBA16(uint4 packed_texels, out uint4 out_01,
// 6e4 has a different exponent bias allowing [0,512) values, 20e4 allows [0,2). // 6e4 has a different exponent bias allowing [0,512) values, 20e4 allows [0,2).
// We also can't clamp the stored value to 1 as load->store->load must be exact. // We also can't clamp the stored value to 1 as load->store->load must be exact.
uint XeFloat32To20e4(uint f32u32) {
// Keep only positive (high bit set means negative for both float and int) and
// saturate to the maximum representable value near 2 (also dropping NaNs).
f32u32 = min((f32u32 <= 0x7FFFFFFFu) ? f32u32 : 0u, 0x3FFFFFF8u);
uint denormalized =
((f32u32 & 0x7FFFFFu) | 0x800000u) >> min(113u - (f32u32 >> 23u), 24u);
uint f24u32 = (f32u32 < 0x38800000u) ? denormalized : (f32u32 + 0xC8000000u);
return ((f24u32 + 3u + ((f24u32 >> 3u) & 1u)) >> 3u) & 0xFFFFFFu;
}
uint4 XeFloat32To20e4(uint4 f32u32) { uint4 XeFloat32To20e4(uint4 f32u32) {
// Keep only positive (high bit set means negative for both float and int) and // Keep only positive (high bit set means negative for both float and int) and
// saturate to the maximum representable value near 2 (also dropping NaNs). // saturate to the maximum representable value near 2 (also dropping NaNs).
@ -505,6 +515,21 @@ uint4 XeFloat32To20e4(uint4 f32u32) {
return ((f24u32 + 3u + ((f24u32 >> 3u) & 1u)) >> 3u) & 0xFFFFFFu; return ((f24u32 + 3u + ((f24u32 >> 3u) & 1u)) >> 3u) & 0xFFFFFFu;
} }
uint XeFloat20e4To32(uint f24u32) {
uint mantissa = f24u32 & 0xFFFFFu;
uint exponent = f24u32 >> 20u;
// Normalize the values for the denormalized components.
// Exponent = 1;
// do { Exponent--; Mantissa <<= 1; } while ((Mantissa & 0x100000) == 0);
bool is_denormalized = exponent == 0u;
uint mantissa_lzcnt = 20u - firstbithigh(mantissa);
exponent = is_denormalized ? (1u - mantissa_lzcnt) : exponent;
mantissa =
is_denormalized ? ((mantissa << mantissa_lzcnt) & 0xFFFFFu) : mantissa;
// Combine into 32-bit float bits and clear zeros.
return (f24u32 != 0u) ? (((exponent + 112u) << 23u) | (mantissa << 3u)) : 0u;
}
uint4 XeFloat20e4To32(uint4 f24u32) { uint4 XeFloat20e4To32(uint4 f24u32) {
uint4 mantissa = f24u32 & 0xFFFFFu; uint4 mantissa = f24u32 & 0xFFFFFu;
uint4 exponent = f24u32 >> 20u; uint4 exponent = f24u32 >> 20u;

View File

@ -10,9 +10,9 @@ void main(point XeVertexPreGS xe_in[1],
} }
XeVertexPostGS xe_out; XeVertexPostGS xe_out;
xe_out.interpolators = xe_in[0].post_gs.interpolators; xe_out.pre_ps.interpolators = xe_in[0].post_gs.pre_ps.interpolators;
xe_out.point_params.z = xe_in[0].post_gs.point_params.z; xe_out.pre_ps.point_params.z = xe_in[0].post_gs.pre_ps.point_params.z;
xe_out.clip_space_zw = xe_in[0].post_gs.clip_space_zw; xe_out.pre_ps.clip_space_zw = xe_in[0].post_gs.pre_ps.clip_space_zw;
xe_out.position.zw = xe_in[0].post_gs.position.zw; xe_out.position.zw = xe_in[0].post_gs.position.zw;
xe_out.clip_distance_0123 = xe_in[0].post_gs.clip_distance_0123; xe_out.clip_distance_0123 = xe_in[0].post_gs.clip_distance_0123;
xe_out.clip_distance_45 = xe_in[0].post_gs.clip_distance_45; xe_out.clip_distance_45 = xe_in[0].post_gs.clip_distance_45;
@ -20,26 +20,27 @@ void main(point XeVertexPreGS xe_in[1],
// Shader header writes -1.0f to point_size by default, so any positive value // Shader header writes -1.0f to point_size by default, so any positive value
// means that it was overwritten by the translated vertex shader. // means that it was overwritten by the translated vertex shader.
float2 point_size = float2 point_size =
(xe_in[0].post_gs.point_params.z > 0.0f ? xe_in[0].post_gs.point_params.zz xe_in[0].post_gs.pre_ps.point_params.z > 0.0f
: xe_point_size); ? xe_in[0].post_gs.pre_ps.point_params.zz
: xe_point_size;
point_size = point_size =
clamp(point_size, xe_point_size_min_max.xx, xe_point_size_min_max.yy) * clamp(point_size, xe_point_size_min_max.xx, xe_point_size_min_max.yy) *
xe_point_screen_to_ndc * xe_in[0].post_gs.position.w; xe_point_screen_to_ndc * xe_in[0].post_gs.position.w;
xe_out.point_params.xy = float2(0.0, 0.0); xe_out.pre_ps.point_params.xy = float2(0.0, 0.0);
// TODO(Triang3l): On Vulkan, sign of Y needs to inverted because of // TODO(Triang3l): On Vulkan, sign of Y needs to inverted because of
// upper-left origin. // upper-left origin.
// TODO(Triang3l): Investigate the true signs of point sprites. // TODO(Triang3l): Investigate the true signs of point sprites.
xe_out.position.xy = xe_out.position.xy =
xe_in[0].post_gs.position.xy + float2(-point_size.x, point_size.y); xe_in[0].post_gs.position.xy + float2(-point_size.x, point_size.y);
xe_stream.Append(xe_out); xe_stream.Append(xe_out);
xe_out.point_params.xy = float2(0.0, 1.0); xe_out.pre_ps.point_params.xy = float2(0.0, 1.0);
xe_out.position.xy = xe_in[0].post_gs.position.xy - point_size; xe_out.position.xy = xe_in[0].post_gs.position.xy - point_size;
xe_stream.Append(xe_out); xe_stream.Append(xe_out);
xe_out.point_params.xy = float2(1.0, 0.0); xe_out.pre_ps.point_params.xy = float2(1.0, 0.0);
xe_out.position.xy = xe_in[0].post_gs.position.xy + point_size; xe_out.position.xy = xe_in[0].post_gs.position.xy + point_size;
xe_stream.Append(xe_out); xe_stream.Append(xe_out);
xe_out.point_params.xy = float2(1.0, 1.0); xe_out.pre_ps.point_params.xy = float2(1.0, 1.0);
xe_out.position.xy = xe_out.position.xy =
xe_in[0].post_gs.position.xy + float2(point_size.x, -point_size.y); xe_in[0].post_gs.position.xy + float2(point_size.x, -point_size.y);
xe_stream.Append(xe_out); xe_stream.Append(xe_out);

View File

@ -80,16 +80,19 @@ void main(triangle XeVertexPreGS xe_in[3],
v3_signs = float3(1.0f, 1.0f, -1.0f); v3_signs = float3(1.0f, 1.0f, -1.0f);
} }
[unroll] for (int i = 0; i < 16; ++i) { [unroll] for (int i = 0; i < 16; ++i) {
xe_out.interpolators[i] = v3_signs.x * xe_in[0].post_gs.interpolators[i] + xe_out.pre_ps.interpolators[i] =
v3_signs.y * xe_in[1].post_gs.interpolators[i] + v3_signs.x * xe_in[0].post_gs.pre_ps.interpolators[i] +
v3_signs.z * xe_in[2].post_gs.interpolators[i]; v3_signs.y * xe_in[1].post_gs.pre_ps.interpolators[i] +
v3_signs.z * xe_in[2].post_gs.pre_ps.interpolators[i];
} }
xe_out.point_params = v3_signs.x * xe_in[0].post_gs.point_params + xe_out.pre_ps.point_params =
v3_signs.y * xe_in[1].post_gs.point_params + v3_signs.x * xe_in[0].post_gs.pre_ps.point_params +
v3_signs.z * xe_in[2].post_gs.point_params; v3_signs.y * xe_in[1].post_gs.pre_ps.point_params +
xe_out.clip_space_zw = v3_signs.x * xe_in[0].post_gs.clip_space_zw + v3_signs.z * xe_in[2].post_gs.pre_ps.point_params;
v3_signs.y * xe_in[1].post_gs.clip_space_zw + xe_out.pre_ps.clip_space_zw =
v3_signs.z * xe_in[2].post_gs.clip_space_zw; v3_signs.x * xe_in[0].post_gs.pre_ps.clip_space_zw +
v3_signs.y * xe_in[1].post_gs.pre_ps.clip_space_zw +
v3_signs.z * xe_in[2].post_gs.pre_ps.clip_space_zw;
xe_out.position = v3_signs.x * xe_in[0].post_gs.position + xe_out.position = v3_signs.x * xe_in[0].post_gs.position +
v3_signs.y * xe_in[1].post_gs.position + v3_signs.y * xe_in[1].post_gs.position +
v3_signs.z * xe_in[2].post_gs.position; v3_signs.z * xe_in[2].post_gs.position;

View File

@ -63,10 +63,14 @@ struct XeHSControlPointOutput {
float index : XEVERTEXID; float index : XEVERTEXID;
}; };
struct XeVertexPostGS { struct XeVertexPrePS {
float4 interpolators[16] : TEXCOORD0; float4 interpolators[16] : TEXCOORD0;
float3 point_params : TEXCOORD16; float3 point_params : TEXCOORD16;
float2 clip_space_zw : TEXCOORD17; float2 clip_space_zw : TEXCOORD17;
};
struct XeVertexPostGS {
XeVertexPrePS pre_ps;
// Precise needed to preserve NaN - guest primitives may be converted to more // Precise needed to preserve NaN - guest primitives may be converted to more
// than 1 triangle, so need to kill them entirely manually in GS if any vertex // than 1 triangle, so need to kill them entirely manually in GS if any vertex
// is NaN. // is NaN.

View File

@ -114,6 +114,7 @@ int32_t FloatToD3D11Fixed16p8(float f32) {
void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x,
float pixel_size_y, bool origin_bottom_left, float pixel_size_y, bool origin_bottom_left,
float x_max, float y_max, bool allow_reverse_z, float x_max, float y_max, bool allow_reverse_z,
bool convert_z_to_float24,
ViewportInfo& viewport_info_out) { ViewportInfo& viewport_info_out) {
assert_true(pixel_size_x >= 1.0f); assert_true(pixel_size_x >= 1.0f);
assert_true(pixel_size_y >= 1.0f); assert_true(pixel_size_y >= 1.0f);
@ -270,6 +271,17 @@ void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x,
ndc_scale_z = -ndc_scale_z; ndc_scale_z = -ndc_scale_z;
ndc_offset_z = 1.0f - ndc_offset_z; ndc_offset_z = 1.0f - ndc_offset_z;
} }
if (convert_z_to_float24 && regs.Get<reg::RB_DEPTHCONTROL>().z_enable &&
regs.Get<reg::RB_DEPTH_INFO>().depth_format ==
xenos::DepthRenderTargetFormat::kD24FS8) {
// Need to adjust the bounds that the resulting depth values will be clamped
// to after the pixel shader. Preferring adding some error to interpolated Z
// instead if conversion can't be done exactly, without modifying clipping
// bounds by adjusting Z in vertex shaders, as that may cause polygons
// placed explicitly at Z = 0 or Z = W to be clipped.
viewport_z_min = xenos::Float20e4To32(xenos::Float32To20e4(viewport_z_min));
viewport_z_max = xenos::Float20e4To32(xenos::Float32To20e4(viewport_z_max));
}
viewport_info_out.left = viewport_left; viewport_info_out.left = viewport_left;
viewport_info_out.top = viewport_top; viewport_info_out.top = viewport_top;

View File

@ -53,6 +53,7 @@ struct ViewportInfo {
void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x, void GetHostViewportInfo(const RegisterFile& regs, float pixel_size_x,
float pixel_size_y, bool origin_bottom_left, float pixel_size_y, bool origin_bottom_left,
float x_max, float y_max, bool allow_reverse_z, float x_max, float y_max, bool allow_reverse_z,
bool convert_z_to_float24,
ViewportInfo& viewport_info_out); ViewportInfo& viewport_info_out);
struct Scissor { struct Scissor {

View File

@ -0,0 +1,27 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/gpu/dxbc_shader.h"
#include <cstring>
namespace xe {
namespace gpu {
DxbcShader::DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count) {}
Shader::Translation* DxbcShader::CreateTranslationInstance(
uint32_t modification) {
return new DxbcTranslation(*this, modification);
}
} // namespace gpu
} // namespace xe

View File

@ -0,0 +1,83 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_DXBC_SHADER_H_
#define XENIA_GPU_DXBC_SHADER_H_
#include <vector>
#include "xenia/gpu/dxbc_shader_translator.h"
#include "xenia/gpu/shader.h"
#include "xenia/gpu/xenos.h"
namespace xe {
namespace gpu {
class DxbcShader : public Shader {
public:
class DxbcTranslation : public Translation {
public:
DxbcTranslation(DxbcShader& shader, uint32_t modification)
: Translation(shader, modification) {}
};
DxbcShader(xenos::ShaderType shader_type, uint64_t data_hash,
const uint32_t* dword_ptr, uint32_t dword_count);
static constexpr uint32_t kMaxTextureBindingIndexBits =
DxbcShaderTranslator::kMaxTextureBindingIndexBits;
static constexpr uint32_t kMaxTextureBindings =
DxbcShaderTranslator::kMaxTextureBindings;
struct TextureBinding {
uint32_t bindless_descriptor_index;
uint32_t fetch_constant;
// Stacked and 3D are separate TextureBindings, even for bindless for null
// descriptor handling simplicity.
xenos::FetchOpDimension dimension;
bool is_signed;
};
// Safe to hash and compare with memcmp for layout hashing.
const TextureBinding* GetTextureBindings(uint32_t& count_out) const {
count_out = uint32_t(texture_bindings_.size());
return texture_bindings_.data();
}
const uint32_t GetUsedTextureMask() const { return used_texture_mask_; }
static constexpr uint32_t kMaxSamplerBindingIndexBits =
DxbcShaderTranslator::kMaxSamplerBindingIndexBits;
static constexpr uint32_t kMaxSamplerBindings =
DxbcShaderTranslator::kMaxSamplerBindings;
struct SamplerBinding {
uint32_t bindless_descriptor_index;
uint32_t fetch_constant;
xenos::TextureFilter mag_filter;
xenos::TextureFilter min_filter;
xenos::TextureFilter mip_filter;
xenos::AnisoFilter aniso_filter;
};
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
count_out = uint32_t(sampler_bindings_.size());
return sampler_bindings_.data();
}
protected:
Translation* CreateTranslationInstance(uint32_t modification) override;
private:
friend class DxbcShaderTranslator;
std::vector<TextureBinding> texture_bindings_;
std::vector<SamplerBinding> sampler_bindings_;
uint32_t used_texture_mask_ = 0;
};
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_DXBC_SHADER_H_

View File

@ -19,6 +19,7 @@
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/cvar.h" #include "xenia/base/cvar.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
#include "xenia/gpu/dxbc_shader.h"
DEFINE_bool(dxbc_switch, true, DEFINE_bool(dxbc_switch, true,
"Use switch rather than if for flow control. Turning this off or " "Use switch rather than if for flow control. Turning this off or "
@ -76,64 +77,31 @@ DxbcShaderTranslator::DxbcShaderTranslator(uint32_t vendor_id,
} }
DxbcShaderTranslator::~DxbcShaderTranslator() = default; DxbcShaderTranslator::~DxbcShaderTranslator() = default;
std::vector<uint8_t> DxbcShaderTranslator::ForceEarlyDepthStencil(
const uint8_t* shader) {
const uint32_t* old_shader = reinterpret_cast<const uint32_t*>(shader);
// To return something anyway even if patching fails.
std::vector<uint8_t> new_shader;
uint32_t shader_size_bytes = old_shader[6];
new_shader.resize(shader_size_bytes);
std::memcpy(new_shader.data(), shader, shader_size_bytes);
// Find the SHEX chunk.
uint32_t chunk_count = old_shader[7];
for (uint32_t i = 0; i < chunk_count; ++i) {
uint32_t chunk_offset_bytes = old_shader[8 + i];
const uint32_t* chunk = old_shader + chunk_offset_bytes / sizeof(uint32_t);
if (chunk[0] != 'XEHS') {
continue;
}
// Find dcl_globalFlags and patch it.
uint32_t code_size_dwords = chunk[3];
chunk += 4;
for (uint32_t j = 0; j < code_size_dwords;) {
uint32_t opcode_token = chunk[j];
uint32_t opcode = DECODE_D3D10_SB_OPCODE_TYPE(opcode_token);
if (opcode == D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS) {
opcode_token |= D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL;
std::memcpy(new_shader.data() +
(chunk_offset_bytes + (4 + j) * sizeof(uint32_t)),
&opcode_token, sizeof(uint32_t));
// Recalculate the checksum since the shader was modified.
CalculateDXBCChecksum(
reinterpret_cast<unsigned char*>(new_shader.data()),
shader_size_bytes,
reinterpret_cast<unsigned int*>(new_shader.data() +
sizeof(uint32_t)));
break;
}
if (opcode == D3D10_SB_OPCODE_CUSTOMDATA) {
j += chunk[j + 1];
} else {
j += DECODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(opcode_token);
}
}
break;
}
return std::move(new_shader);
}
std::vector<uint8_t> DxbcShaderTranslator::CreateDepthOnlyPixelShader() { std::vector<uint8_t> DxbcShaderTranslator::CreateDepthOnlyPixelShader() {
Reset(); Reset(xenos::ShaderType::kPixel);
is_depth_only_pixel_shader_ = true; is_depth_only_pixel_shader_ = true;
StartTranslation(); StartTranslation();
return std::move(CompleteTranslation()); return std::move(CompleteTranslation());
} }
void DxbcShaderTranslator::Reset() { uint32_t DxbcShaderTranslator::GetDefaultModification(
ShaderTranslator::Reset(); xenos::ShaderType shader_type,
Shader::HostVertexShaderType host_vertex_shader_type) const {
Modification shader_modification;
switch (shader_type) {
case xenos::ShaderType::kVertex:
shader_modification.host_vertex_shader_type = host_vertex_shader_type;
break;
case xenos::ShaderType::kPixel:
shader_modification.depth_stencil_mode =
Modification::DepthStencilMode::kNoModifiers;
break;
}
return shader_modification.value;
}
void DxbcShaderTranslator::Reset(xenos::ShaderType shader_type) {
ShaderTranslator::Reset(shader_type);
shader_code_.clear(); shader_code_.clear();
@ -152,7 +120,7 @@ void DxbcShaderTranslator::Reset() {
in_domain_location_used_ = 0; in_domain_location_used_ = 0;
in_primitive_id_used_ = false; in_primitive_id_used_ = false;
in_control_point_index_used_ = false; in_control_point_index_used_ = false;
in_position_xy_used_ = false; in_position_used_ = 0;
in_front_face_used_ = false; in_front_face_used_ = false;
system_temp_count_current_ = 0; system_temp_count_current_ = 0;
@ -457,7 +425,9 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() {
// Remember that x# are only accessible via mov load or store - use a // Remember that x# are only accessible via mov load or store - use a
// temporary variable if need to do any computations! // temporary variable if need to do any computations!
switch (host_vertex_shader_type()) { Shader::HostVertexShaderType host_vertex_shader_type =
GetDxbcShaderModification().host_vertex_shader_type;
switch (host_vertex_shader_type) {
case Shader::HostVertexShaderType::kVertex: case Shader::HostVertexShaderType::kVertex:
StartVertexShader_LoadVertexIndex(); StartVertexShader_LoadVertexIndex();
break; break;
@ -618,7 +588,7 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() {
default: default:
// TODO(Triang3l): Support line and non-adaptive quad patches. // TODO(Triang3l): Support line and non-adaptive quad patches.
assert_unhandled_case(host_vertex_shader_type()); assert_unhandled_case(host_vertex_shader_type);
EmitTranslationError( EmitTranslationError(
"Unsupported host vertex shader type in StartVertexOrDomainShader"); "Unsupported host vertex shader type in StartVertexOrDomainShader");
break; break;
@ -720,7 +690,7 @@ void DxbcShaderTranslator::StartPixelShader() {
// faceness as X sign bit. Using Z as scratch register now. // faceness as X sign bit. Using Z as scratch register now.
if (edram_rov_used_) { if (edram_rov_used_) {
// Get XY address of the current host pixel as float. // Get XY address of the current host pixel as float.
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
DxbcOpRoundZ(DxbcDest::R(param_gen_temp, 0b0011), DxbcOpRoundZ(DxbcDest::R(param_gen_temp, 0b0011),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition))); DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
// Revert resolution scale - after truncating, so if the pixel position // Revert resolution scale - after truncating, so if the pixel position
@ -744,7 +714,7 @@ void DxbcShaderTranslator::StartPixelShader() {
} else { } else {
// Get XY address of the current SSAA sample by converting // Get XY address of the current SSAA sample by converting
// SV_Position.xy to an integer. // SV_Position.xy to an integer.
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
DxbcOpFToU(DxbcDest::R(param_gen_temp, 0b0011), DxbcOpFToU(DxbcDest::R(param_gen_temp, 0b0011),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition))); DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
// Undo SSAA that is used instead of MSAA - since it's used as a // Undo SSAA that is used instead of MSAA - since it's used as a
@ -870,7 +840,7 @@ void DxbcShaderTranslator::StartPixelShader() {
void DxbcShaderTranslator::StartTranslation() { void DxbcShaderTranslator::StartTranslation() {
// Allocate global system temporary registers that may also be used in the // Allocate global system temporary registers that may also be used in the
// epilogue. // epilogue.
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
system_temp_position_ = PushSystemTemp(0b1111); system_temp_position_ = PushSystemTemp(0b1111);
system_temp_point_size_edge_flag_kill_vertex_ = PushSystemTemp(0b0100); system_temp_point_size_edge_flag_kill_vertex_ = PushSystemTemp(0b0100);
// Set the point size to a negative value to tell the geometry shader that // Set the point size to a negative value to tell the geometry shader that
@ -879,20 +849,21 @@ void DxbcShaderTranslator::StartTranslation() {
DxbcOpMov( DxbcOpMov(
DxbcDest::R(system_temp_point_size_edge_flag_kill_vertex_, 0b0001), DxbcDest::R(system_temp_point_size_edge_flag_kill_vertex_, 0b0001),
DxbcSrc::LF(-1.0f)); DxbcSrc::LF(-1.0f));
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
if (edram_rov_used_) { if (edram_rov_used_) {
// Will be initialized unconditionally. // Will be initialized unconditionally.
system_temp_rov_params_ = PushSystemTemp(); system_temp_rov_params_ = PushSystemTemp();
if (ROV_IsDepthStencilEarly() || writes_depth()) { }
// If the shader doesn't write to oDepth, each component will be written if (IsDepthStencilSystemTempUsed()) {
// to if depth/stencil is enabled and the respective sample is covered - // If the shader doesn't write to oDepth, and ROV is used, each
// so need to initialize now because the first writes will be // component will be written to if depth/stencil is enabled and the
// conditional. If the shader writes to oDepth, this is oDepth of the // respective sample is covered - so need to initialize now because the
// shader, written by the guest code, so initialize because assumptions // first writes will be conditional.
// can't be made about the integrity of the guest code. // If the shader writes to oDepth, this is oDepth of the shader, written
system_temp_rov_depth_stencil_ = // by the guest code, so initialize because assumptions can't be made
PushSystemTemp(writes_depth() ? 0b0001 : 0b1111); // about the integrity of the guest code.
} system_temp_depth_stencil_ =
PushSystemTemp(writes_depth() ? 0b0001 : 0b1111);
} }
for (uint32_t i = 0; i < 4; ++i) { for (uint32_t i = 0; i < 4; ++i) {
if (writes_color_target(i)) { if (writes_color_target(i)) {
@ -942,7 +913,7 @@ void DxbcShaderTranslator::StartTranslation() {
// Zero general-purpose registers to prevent crashes when the game // Zero general-purpose registers to prevent crashes when the game
// references them after only initializing them conditionally. // references them after only initializing them conditionally.
for (uint32_t i = IsDxbcPixelShader() ? xenos::kMaxInterpolators : 0; for (uint32_t i = is_pixel_shader() ? xenos::kMaxInterpolators : 0;
i < register_count(); ++i) { i < register_count(); ++i) {
DxbcOpMov(uses_register_dynamic_addressing() ? DxbcDest::X(0, i) DxbcOpMov(uses_register_dynamic_addressing() ? DxbcDest::X(0, i)
: DxbcDest::R(i), : DxbcDest::R(i),
@ -951,9 +922,9 @@ void DxbcShaderTranslator::StartTranslation() {
} }
// Write stage-specific prologue. // Write stage-specific prologue.
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
StartVertexOrDomainShader(); StartVertexOrDomainShader();
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
StartPixelShader(); StartPixelShader();
} }
@ -1168,31 +1139,31 @@ void DxbcShaderTranslator::CompleteShaderCode() {
} }
// Write stage-specific epilogue. // Write stage-specific epilogue.
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
CompleteVertexOrDomainShader(); CompleteVertexOrDomainShader();
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
CompletePixelShader(); CompletePixelShader();
} }
// Return from `main`. // Return from `main`.
DxbcOpRet(); DxbcOpRet();
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
// Release system_temp_position_ and // Release system_temp_position_ and
// system_temp_point_size_edge_flag_kill_vertex_. // system_temp_point_size_edge_flag_kill_vertex_.
PopSystemTemp(2); PopSystemTemp(2);
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
// Release system_temps_color_. // Release system_temps_color_.
for (int32_t i = 3; i >= 0; --i) { for (int32_t i = 3; i >= 0; --i) {
if (writes_color_target(i)) { if (writes_color_target(i)) {
PopSystemTemp(); PopSystemTemp();
} }
} }
if (IsDepthStencilSystemTempUsed()) {
// Release system_temp_depth_stencil_.
PopSystemTemp();
}
if (edram_rov_used_) { if (edram_rov_used_) {
if (ROV_IsDepthStencilEarly() || writes_depth()) {
// Release system_temp_rov_depth_stencil_.
PopSystemTemp();
}
// Release system_temp_rov_params_. // Release system_temp_rov_params_.
PopSystemTemp(); PopSystemTemp();
} }
@ -1303,6 +1274,44 @@ std::vector<uint8_t> DxbcShaderTranslator::CompleteTranslation() {
return shader_object_bytes; return shader_object_bytes;
} }
void DxbcShaderTranslator::PostTranslation(
Shader::Translation& translation, bool setup_shader_post_translation_info) {
if (setup_shader_post_translation_info) {
DxbcShader* dxbc_shader = dynamic_cast<DxbcShader*>(&translation.shader());
if (dxbc_shader) {
dxbc_shader->texture_bindings_.clear();
dxbc_shader->texture_bindings_.reserve(texture_bindings_.size());
dxbc_shader->used_texture_mask_ = 0;
for (const TextureBinding& translator_binding : texture_bindings_) {
DxbcShader::TextureBinding& shader_binding =
dxbc_shader->texture_bindings_.emplace_back();
// For a stable hash.
std::memset(&shader_binding, 0, sizeof(shader_binding));
shader_binding.bindless_descriptor_index =
translator_binding.bindless_descriptor_index;
shader_binding.fetch_constant = translator_binding.fetch_constant;
shader_binding.dimension = translator_binding.dimension;
shader_binding.is_signed = translator_binding.is_signed;
dxbc_shader->used_texture_mask_ |= 1u
<< translator_binding.fetch_constant;
}
dxbc_shader->sampler_bindings_.clear();
dxbc_shader->sampler_bindings_.reserve(sampler_bindings_.size());
for (const SamplerBinding& translator_binding : sampler_bindings_) {
DxbcShader::SamplerBinding& shader_binding =
dxbc_shader->sampler_bindings_.emplace_back();
shader_binding.bindless_descriptor_index =
translator_binding.bindless_descriptor_index;
shader_binding.fetch_constant = translator_binding.fetch_constant;
shader_binding.mag_filter = translator_binding.mag_filter;
shader_binding.min_filter = translator_binding.min_filter;
shader_binding.mip_filter = translator_binding.mip_filter;
shader_binding.aniso_filter = translator_binding.aniso_filter;
}
}
}
}
void DxbcShaderTranslator::EmitInstructionDisassembly() { void DxbcShaderTranslator::EmitInstructionDisassembly() {
if (!emit_source_map_) { if (!emit_source_map_) {
return; return;
@ -1527,19 +1536,20 @@ void DxbcShaderTranslator::StoreResult(const InstructionResult& result,
} }
break; break;
case InstructionStorageTarget::kDepth: case InstructionStorageTarget::kDepth:
// Writes X to scalar oDepth or to X of system_temp_rov_depth_stencil_, no // Writes X to scalar oDepth or to X of system_temp_depth_stencil_, no
// additional swizzling needed. // additional swizzling needed.
assert_true(used_write_mask == 0b0001); assert_true(used_write_mask == 0b0001);
assert_true(writes_depth()); assert_true(writes_depth());
if (edram_rov_used_) { if (IsDepthStencilSystemTempUsed()) {
dest = DxbcDest::R(system_temp_rov_depth_stencil_); dest = DxbcDest::R(system_temp_depth_stencil_);
} else { } else {
dest = DxbcDest::ODepth(); dest = DxbcDest::ODepth();
} }
// Depth outside [0, 1] is not safe for use with the ROV code. Though 20e4 // Depth outside [0, 1] is not safe for use with the ROV code and with
// float depth can store values below 2, it's a very unusual case. // 20e4-as-32 conversion. Though 20e4 float depth can store values between
// Direct3D 10+ SV_Depth, however, can accept any values, including // 1 and 2, it's a very unusual case. Direct3D 10+ SV_Depth, however, can
// specials, when the depth buffer is floating-point. // accept any values, including specials, when the depth buffer is
// floating-point; but depth is clamped to the viewport bounds anyway.
is_clamped = true; is_clamped = true;
break; break;
} }
@ -2094,7 +2104,7 @@ void DxbcShaderTranslator::WriteResourceDefinitions() {
// ds_5_1 // ds_5_1
shader_object_.push_back(0x44530501u); shader_object_.push_back(0x44530501u);
} else { } else {
assert_true(IsDxbcPixelShader()); assert_true(is_pixel_shader());
// ps_5_1 // ps_5_1
shader_object_.push_back(0xFFFF0501u); shader_object_.push_back(0xFFFF0501u);
} }
@ -2765,7 +2775,7 @@ void DxbcShaderTranslator::WriteInputSignature() {
control_point_index.semantic_name = semantic_offset; control_point_index.semantic_name = semantic_offset;
} }
semantic_offset += AppendString(shader_object_, "XEVERTEXID"); semantic_offset += AppendString(shader_object_, "XEVERTEXID");
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
// Written dynamically, so assume it's always used if it can be written to // Written dynamically, so assume it's always used if it can be written to
// any interpolator register. // any interpolator register.
bool param_gen_used = !is_depth_only_pixel_shader_ && register_count() != 0; bool param_gen_used = !is_depth_only_pixel_shader_ && register_count() != 0;
@ -2843,7 +2853,7 @@ void DxbcShaderTranslator::WriteInputSignature() {
position.component_type = DxbcSignatureRegisterComponentType::kFloat32; position.component_type = DxbcSignatureRegisterComponentType::kFloat32;
position.register_index = uint32_t(InOutRegister::kPSInPosition); position.register_index = uint32_t(InOutRegister::kPSInPosition);
position.mask = 0b1111; position.mask = 0b1111;
position.always_reads_mask = in_position_xy_used_ ? 0b0011 : 0b0000; position.always_reads_mask = in_position_used_;
} }
// Is front face (SV_IsFrontFace). // Is front face (SV_IsFrontFace).
@ -2927,7 +2937,9 @@ void DxbcShaderTranslator::WritePatchConstantSignature() {
DxbcName tess_factor_edge_system_value = DxbcName::kUndefined; DxbcName tess_factor_edge_system_value = DxbcName::kUndefined;
uint32_t tess_factor_inside_count = 0; uint32_t tess_factor_inside_count = 0;
DxbcName tess_factor_inside_system_value = DxbcName::kUndefined; DxbcName tess_factor_inside_system_value = DxbcName::kUndefined;
switch (host_vertex_shader_type()) { Shader::HostVertexShaderType host_vertex_shader_type =
GetDxbcShaderModification().host_vertex_shader_type;
switch (host_vertex_shader_type) {
case Shader::HostVertexShaderType::kTriangleDomainCPIndexed: case Shader::HostVertexShaderType::kTriangleDomainCPIndexed:
case Shader::HostVertexShaderType::kTriangleDomainPatchIndexed: case Shader::HostVertexShaderType::kTriangleDomainPatchIndexed:
tess_factor_edge_count = 3; tess_factor_edge_count = 3;
@ -2944,7 +2956,7 @@ void DxbcShaderTranslator::WritePatchConstantSignature() {
break; break;
default: default:
// TODO(Triang3l): Support line patches. // TODO(Triang3l): Support line patches.
assert_unhandled_case(host_vertex_shader_type()); assert_unhandled_case(host_vertex_shader_type);
EmitTranslationError( EmitTranslationError(
"Unsupported host vertex shader type in WritePatchConstantSignature"); "Unsupported host vertex shader type in WritePatchConstantSignature");
} }
@ -3033,7 +3045,7 @@ void DxbcShaderTranslator::WriteOutputSignature() {
constexpr size_t kParameterDwords = constexpr size_t kParameterDwords =
sizeof(DxbcSignatureParameter) / sizeof(uint32_t); sizeof(DxbcSignatureParameter) / sizeof(uint32_t);
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
// Intepolators (TEXCOORD#). // Intepolators (TEXCOORD#).
size_t interpolator_position = shader_object_.size(); size_t interpolator_position = shader_object_.size();
shader_object_.resize(shader_object_.size() + shader_object_.resize(shader_object_.size() +
@ -3195,7 +3207,7 @@ void DxbcShaderTranslator::WriteOutputSignature() {
cull_distance.semantic_name = semantic_offset; cull_distance.semantic_name = semantic_offset;
} }
semantic_offset += AppendString(shader_object_, "SV_CullDistance"); semantic_offset += AppendString(shader_object_, "SV_CullDistance");
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
if (!edram_rov_used_) { if (!edram_rov_used_) {
// Color render targets (SV_Target#). // Color render targets (SV_Target#).
size_t target_position = SIZE_MAX; size_t target_position = SIZE_MAX;
@ -3217,9 +3229,11 @@ void DxbcShaderTranslator::WriteOutputSignature() {
} }
} }
// Depth (SV_Depth). // Depth (SV_Depth or SV_DepthLessEqual).
Modification::DepthStencilMode depth_stencil_mode =
GetDxbcShaderModification().depth_stencil_mode;
size_t depth_position = SIZE_MAX; size_t depth_position = SIZE_MAX;
if (writes_depth()) { if (writes_depth() || DSV_IsWritingFloat24Depth()) {
depth_position = shader_object_.size(); depth_position = shader_object_.size();
shader_object_.resize(shader_object_.size() + kParameterDwords); shader_object_.resize(shader_object_.size() + kParameterDwords);
++parameter_count; ++parameter_count;
@ -3253,7 +3267,15 @@ void DxbcShaderTranslator::WriteOutputSignature() {
depth_position); depth_position);
depth.semantic_name = semantic_offset; depth.semantic_name = semantic_offset;
} }
semantic_offset += AppendString(shader_object_, "SV_Depth"); const char* depth_semantic_name;
if (!writes_depth() &&
GetDxbcShaderModification().depth_stencil_mode ==
Modification::DepthStencilMode::kFloat24Truncating) {
depth_semantic_name = "SV_DepthLessEqual";
} else {
depth_semantic_name = "SV_Depth";
}
semantic_offset += AppendString(shader_object_, depth_semantic_name);
} }
} }
} }
@ -3276,7 +3298,7 @@ void DxbcShaderTranslator::WriteShaderCode() {
} else if (IsDxbcDomainShader()) { } else if (IsDxbcDomainShader()) {
shader_type = D3D11_SB_DOMAIN_SHADER; shader_type = D3D11_SB_DOMAIN_SHADER;
} else { } else {
assert_true(IsDxbcPixelShader()); assert_true(is_pixel_shader());
shader_type = D3D10_SB_PIXEL_SHADER; shader_type = D3D10_SB_PIXEL_SHADER;
} }
shader_object_.push_back( shader_object_.push_back(
@ -3296,12 +3318,14 @@ void DxbcShaderTranslator::WriteShaderCode() {
// Inputs/outputs have 1D-indexed operands with a component mask and a // Inputs/outputs have 1D-indexed operands with a component mask and a
// register index. // register index.
Modification shader_modification = GetDxbcShaderModification();
if (IsDxbcDomainShader()) { if (IsDxbcDomainShader()) {
// Not using control point data since Xenos only has a vertex shader acting // Not using control point data since Xenos only has a vertex shader acting
// as both vertex shader and domain shader. // as both vertex shader and domain shader.
stat_.c_control_points = 3; stat_.c_control_points = 3;
stat_.tessellator_domain = DxbcTessellatorDomain::kTriangle; stat_.tessellator_domain = DxbcTessellatorDomain::kTriangle;
switch (host_vertex_shader_type()) { switch (shader_modification.host_vertex_shader_type) {
case Shader::HostVertexShaderType::kTriangleDomainCPIndexed: case Shader::HostVertexShaderType::kTriangleDomainCPIndexed:
case Shader::HostVertexShaderType::kTriangleDomainPatchIndexed: case Shader::HostVertexShaderType::kTriangleDomainPatchIndexed:
stat_.c_control_points = 3; stat_.c_control_points = 3;
@ -3314,7 +3338,7 @@ void DxbcShaderTranslator::WriteShaderCode() {
break; break;
default: default:
// TODO(Triang3l): Support line patches. // TODO(Triang3l): Support line patches.
assert_unhandled_case(host_vertex_shader_type()); assert_unhandled_case(shader_modification.host_vertex_shader_type);
EmitTranslationError( EmitTranslationError(
"Unsupported host vertex shader type in WriteShaderCode"); "Unsupported host vertex shader type in WriteShaderCode");
} }
@ -3330,11 +3354,17 @@ void DxbcShaderTranslator::WriteShaderCode() {
} }
// Don't allow refactoring when converting to native code to maintain position // Don't allow refactoring when converting to native code to maintain position
// invariance (needed even in pixel shaders for oDepth invariance). Also this // invariance (needed even in pixel shaders for oDepth invariance).
// dcl will be modified by ForceEarlyDepthStencil. uint32_t global_flags_opcode =
shader_object_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS) | ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1)); ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(1);
if (is_pixel_shader() &&
GetDxbcShaderModification().depth_stencil_mode ==
Modification::DepthStencilMode::kEarlyHint &&
!edram_rov_used_ && CanWriteZEarly()) {
global_flags_opcode |= D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL;
}
shader_object_.push_back(global_flags_opcode);
// Constant buffers, from most frequenly accessed to least frequently accessed // Constant buffers, from most frequenly accessed to least frequently accessed
// (the order is a hint to the driver according to the DXBC header). // (the order is a hint to the driver according to the DXBC header).
@ -3560,7 +3590,7 @@ void DxbcShaderTranslator::WriteShaderCode() {
} }
// Inputs and outputs. // Inputs and outputs.
if (IsDxbcVertexOrDomainShader()) { if (is_vertex_shader()) {
if (IsDxbcDomainShader()) { if (IsDxbcDomainShader()) {
if (in_domain_location_used_) { if (in_domain_location_used_) {
// Domain location input. // Domain location input.
@ -3584,7 +3614,7 @@ void DxbcShaderTranslator::WriteShaderCode() {
if (in_control_point_index_used_) { if (in_control_point_index_used_) {
// Control point indices as float input. // Control point indices as float input.
uint32_t control_point_array_size; uint32_t control_point_array_size;
switch (host_vertex_shader_type()) { switch (shader_modification.host_vertex_shader_type) {
case Shader::HostVertexShaderType::kTriangleDomainCPIndexed: case Shader::HostVertexShaderType::kTriangleDomainCPIndexed:
control_point_array_size = 3; control_point_array_size = 3;
break; break;
@ -3593,7 +3623,7 @@ void DxbcShaderTranslator::WriteShaderCode() {
break; break;
default: default:
// TODO(Triang3l): Support line patches. // TODO(Triang3l): Support line patches.
assert_unhandled_case(host_vertex_shader_type()); assert_unhandled_case(shader_modification.host_vertex_shader_type);
EmitTranslationError( EmitTranslationError(
"Unsupported host vertex shader type in " "Unsupported host vertex shader type in "
"StartVertexOrDomainShader"); "StartVertexOrDomainShader");
@ -3683,7 +3713,8 @@ void DxbcShaderTranslator::WriteShaderCode() {
uint32_t(InOutRegister::kVSDSOutClipDistance45AndCullDistance)); uint32_t(InOutRegister::kVSDSOutClipDistance45AndCullDistance));
shader_object_.push_back(ENCODE_D3D10_SB_NAME(D3D10_SB_NAME_CULL_DISTANCE)); shader_object_.push_back(ENCODE_D3D10_SB_NAME(D3D10_SB_NAME_CULL_DISTANCE));
++stat_.dcl_count; ++stat_.dcl_count;
} else if (IsDxbcPixelShader()) { } else if (is_pixel_shader()) {
bool is_writing_float24_depth = DSV_IsWritingFloat24Depth();
// Interpolator input. // Interpolator input.
if (!is_depth_only_pixel_shader_) { if (!is_depth_only_pixel_shader_) {
uint32_t interpolator_count = uint32_t interpolator_count =
@ -3725,16 +3756,26 @@ void DxbcShaderTranslator::WriteShaderCode() {
shader_object_.push_back(uint32_t(InOutRegister::kPSInClipSpaceZW)); shader_object_.push_back(uint32_t(InOutRegister::kPSInClipSpaceZW));
++stat_.dcl_count; ++stat_.dcl_count;
} }
if (in_position_xy_used_) { if (in_position_used_) {
// Position input (only XY needed for ps_param_gen, and the ROV depth code // Position input (XY needed for ps_param_gen, Z needed for non-ROV
// calculates the depth from clip space Z and W). // float24 conversion; the ROV depth code calculates the depth the from
// clip space Z and W with pull-mode per-sample interpolation instead).
// At the cost of possibility of MSAA with pixel-rate shading, need
// per-sample depth - otherwise intersections cannot be antialiased, and
// with SV_DepthLessEqual, per-sample (or centroid, but this isn't
// applicable here) position is mandatory. However, with depth output, on
// the guest, there's only one depth value for the whole pixel.
D3D10_SB_INTERPOLATION_MODE position_interpolation_mode =
is_writing_float24_depth && !writes_depth()
? D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE
: D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE;
shader_object_.push_back( shader_object_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_INPUT_PS_SIV) | ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_INPUT_PS_SIV) |
ENCODE_D3D10_SB_INPUT_INTERPOLATION_MODE( ENCODE_D3D10_SB_INPUT_INTERPOLATION_MODE(
D3D10_SB_INTERPOLATION_LINEAR_NOPERSPECTIVE) | position_interpolation_mode) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(4)); ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(4));
shader_object_.push_back( shader_object_.push_back(EncodeVectorMaskedOperand(
EncodeVectorMaskedOperand(D3D10_SB_OPERAND_TYPE_INPUT, 0b0011, 1)); D3D10_SB_OPERAND_TYPE_INPUT, in_position_used_, 1));
shader_object_.push_back(uint32_t(InOutRegister::kPSInPosition)); shader_object_.push_back(uint32_t(InOutRegister::kPSInPosition));
shader_object_.push_back(ENCODE_D3D10_SB_NAME(D3D10_SB_NAME_POSITION)); shader_object_.push_back(ENCODE_D3D10_SB_NAME(D3D10_SB_NAME_POSITION));
++stat_.dcl_count; ++stat_.dcl_count;
@ -3778,12 +3819,19 @@ void DxbcShaderTranslator::WriteShaderCode() {
} }
} }
// Depth output. // Depth output.
if (writes_depth()) { if (is_writing_float24_depth || writes_depth()) {
D3D10_SB_OPERAND_TYPE depth_operand_type;
if (!writes_depth() &&
GetDxbcShaderModification().depth_stencil_mode ==
Modification::DepthStencilMode::kFloat24Truncating) {
depth_operand_type = D3D11_SB_OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL;
} else {
depth_operand_type = D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH;
}
shader_object_.push_back( shader_object_.push_back(
ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_OUTPUT) | ENCODE_D3D10_SB_OPCODE_TYPE(D3D10_SB_OPCODE_DCL_OUTPUT) |
ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(2)); ENCODE_D3D10_SB_TOKENIZED_INSTRUCTION_LENGTH(2));
shader_object_.push_back( shader_object_.push_back(EncodeScalarOperand(depth_operand_type, 0));
EncodeScalarOperand(D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH, 0));
++stat_.dcl_count; ++stat_.dcl_count;
} }
} }

View File

@ -102,6 +102,51 @@ class DxbcShaderTranslator : public ShaderTranslator {
bool edram_rov_used, bool force_emit_source_map = false); bool edram_rov_used, bool force_emit_source_map = false);
~DxbcShaderTranslator() override; ~DxbcShaderTranslator() override;
union Modification {
// If anything in this is structure is changed in a way not compatible with
// the previous layout, invalidate the pipeline storages by increasing this
// version number (0xYYYYMMDD)!
static constexpr uint32_t kVersion = 0x20201203;
enum class DepthStencilMode : uint32_t {
kNoModifiers,
// [earlydepthstencil] - enable if alpha test and alpha to coverage are
// disabled; ignored if anything in the shader blocks early Z writing
// (which is not known before translation, so this will be set anyway).
kEarlyHint,
// Converting the depth to the closest 32-bit float representable exactly
// as a 20e4 float, to support invariance in cases when the guest
// reuploads a previously resolved depth buffer to the EDRAM, rounding
// towards zero (which contradicts the rounding used by the Direct3D 9
// reference rasterizer, but allows SV_DepthLessEqual to be used to allow
// slightly coarse early Z culling; also truncating regardless of whether
// the shader writes depth and thus always uses SV_Depth, for
// consistency). MSAA is limited - depth must be per-sample
// (SV_DepthLessEqual also explicitly requires sample or centroid position
// interpolation), thus the sampler has to run at sample frequency even if
// the device supports stencil loading and thus true non-ROV MSAA via
// SV_StencilRef.
// Fixed-function viewport depth bounds must be snapped to float24 for
// clamping purposes.
kFloat24Truncating,
// Similar to kFloat24Truncating, but rounding to the nearest even,
// however, always using SV_Depth rather than SV_DepthLessEqual because
// rounding up results in a bigger value. Same viewport usage rules apply.
kFloat24Rounding,
};
struct {
// VS - pipeline stage and input configuration.
Shader::HostVertexShaderType host_vertex_shader_type
: Shader::kHostVertexShaderTypeBitCount;
// PS, non-ROV - depth / stencil output mode.
DepthStencilMode depth_stencil_mode : 2;
};
uint32_t value = 0;
Modification(uint32_t modification_value = 0) : value(modification_value) {}
};
// Constant buffer bindings in space 0. // Constant buffer bindings in space 0.
enum class CbufferRegister { enum class CbufferRegister {
kSystemConstants, kSystemConstants,
@ -238,15 +283,15 @@ class DxbcShaderTranslator : public ShaderTranslator {
// EDRAM address calculation. // EDRAM address calculation.
uint32_t sample_count_log2[2]; uint32_t sample_count_log2[2];
float alpha_test_reference; float alpha_test_reference;
// If alpha to mask is disabled, the entire alpha_to_mask value must be 0.
// If alpha to mask is enabled, bits 0:7 are sample offsets, and bit 8 must
// be 1.
uint32_t alpha_to_mask; uint32_t alpha_to_mask;
float color_exp_bias[4]; float color_exp_bias[4];
uint32_t color_output_map[4]; uint32_t color_output_map[4];
// If alpha to mask is disabled, the entire alpha_to_mask value must be 0.
// If alpha to mask is enabled, bits 0:7 are sample offsets, and bit 8 must
// be 1.
uint32_t edram_resolution_square_scale; uint32_t edram_resolution_square_scale;
uint32_t edram_pitch_tiles; uint32_t edram_pitch_tiles;
union { union {
@ -358,12 +403,6 @@ class DxbcShaderTranslator : public ShaderTranslator {
bool is_signed; bool is_signed;
std::string name; std::string name;
}; };
// The first binding returned is at t[SRVMainRegister::kBindfulTexturesStart]
// of space SRVSpace::kMain.
const TextureBinding* GetTextureBindings(uint32_t& count_out) const {
count_out = uint32_t(texture_bindings_.size());
return texture_bindings_.data();
}
// Arbitrary limit - there can't be more than 2048 in a shader-visible // Arbitrary limit - there can't be more than 2048 in a shader-visible
// descriptor heap, though some older hardware (tier 1 resource binding - // descriptor heap, though some older hardware (tier 1 resource binding -
@ -385,16 +424,6 @@ class DxbcShaderTranslator : public ShaderTranslator {
xenos::AnisoFilter aniso_filter; xenos::AnisoFilter aniso_filter;
std::string name; std::string name;
}; };
const SamplerBinding* GetSamplerBindings(uint32_t& count_out) const {
count_out = uint32_t(sampler_bindings_.size());
return sampler_bindings_.data();
}
// Returns the number of texture SRV and sampler offsets that need to be
// passed via a constant buffer to the shader.
uint32_t GetBindlessResourceCount() const {
return uint32_t(texture_bindings_.size() + sampler_bindings_.size());
}
// Unordered access view bindings in space 0. // Unordered access view bindings in space 0.
enum class UAVRegister { enum class UAVRegister {
@ -402,10 +431,6 @@ class DxbcShaderTranslator : public ShaderTranslator {
kEdram, kEdram,
}; };
// Creates a copy of the shader with early depth/stencil testing forced,
// overriding that alpha testing is used in the shader.
static std::vector<uint8_t> ForceEarlyDepthStencil(const uint8_t* shader);
// Returns the format with internal flags for passing via the // Returns the format with internal flags for passing via the
// edram_rt_format_flags system constant. // edram_rt_format_flags system constant.
static constexpr uint32_t ROV_AddColorFormatFlags( static constexpr uint32_t ROV_AddColorFormatFlags(
@ -440,16 +465,22 @@ class DxbcShaderTranslator : public ShaderTranslator {
float& clamp_alpha_high, uint32_t& keep_mask_low, float& clamp_alpha_high, uint32_t& keep_mask_low,
uint32_t& keep_mask_high); uint32_t& keep_mask_high);
uint32_t GetDefaultModification(
xenos::ShaderType shader_type,
Shader::HostVertexShaderType host_vertex_shader_type =
Shader::HostVertexShaderType::kVertex) const override;
// Creates a special pixel shader without color outputs - this resets the // Creates a special pixel shader without color outputs - this resets the
// state of the translator. // state of the translator.
std::vector<uint8_t> CreateDepthOnlyPixelShader(); std::vector<uint8_t> CreateDepthOnlyPixelShader();
protected: protected:
void Reset() override; void Reset(xenos::ShaderType shader_type) override;
void StartTranslation() override; void StartTranslation() override;
std::vector<uint8_t> CompleteTranslation() override; std::vector<uint8_t> CompleteTranslation() override;
void PostTranslation(Shader::Translation& translation,
bool setup_shader_post_translation_info) override;
void ProcessLabel(uint32_t cf_index) override; void ProcessLabel(uint32_t cf_index) override;
@ -650,6 +681,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
kInputDomainPoint = 28, kInputDomainPoint = 28,
kUnorderedAccessView = 30, kUnorderedAccessView = 30,
kInputCoverageMask = 35, kInputCoverageMask = 35,
kOutputDepthLessEqual = 39,
}; };
// D3D10_SB_OPERAND_INDEX_DIMENSION // D3D10_SB_OPERAND_INDEX_DIMENSION
@ -689,6 +721,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
return DxbcOperandDimension::kNoData; return DxbcOperandDimension::kNoData;
case DxbcOperandType::kInputPrimitiveID: case DxbcOperandType::kInputPrimitiveID:
case DxbcOperandType::kOutputDepth: case DxbcOperandType::kOutputDepth:
case DxbcOperandType::kOutputDepthLessEqual:
return DxbcOperandDimension::kScalar; return DxbcOperandDimension::kScalar;
case DxbcOperandType::kInputCoverageMask: case DxbcOperandType::kInputCoverageMask:
return dest_in_dcl ? DxbcOperandDimension::kScalar return dest_in_dcl ? DxbcOperandDimension::kScalar
@ -860,6 +893,9 @@ class DxbcShaderTranslator : public ShaderTranslator {
return DxbcDest(DxbcOperandType::kUnorderedAccessView, write_mask, return DxbcDest(DxbcOperandType::kUnorderedAccessView, write_mask,
index_1d, index_2d); index_1d, index_2d);
} }
static DxbcDest ODepthLE() {
return DxbcDest(DxbcOperandType::kOutputDepthLessEqual, 0b0001);
}
uint32_t GetMask() const { uint32_t GetMask() const {
switch (GetDimension()) { switch (GetDimension()) {
@ -2145,21 +2181,19 @@ class DxbcShaderTranslator : public ShaderTranslator {
(index_representation_1 << 25) | (index_representation_2 << 28); (index_representation_1 << 25) | (index_representation_2 << 28);
} }
// Use these instead of is_vertex_shader/is_pixel_shader because they don't Modification GetDxbcShaderModification() const {
// take is_depth_only_pixel_shader_ into account. return Modification(modification());
inline bool IsDxbcVertexOrDomainShader() const {
return !is_depth_only_pixel_shader_ && is_vertex_shader();
} }
inline bool IsDxbcVertexShader() const {
return IsDxbcVertexOrDomainShader() && bool IsDxbcVertexShader() const {
host_vertex_shader_type() == Shader::HostVertexShaderType::kVertex; return is_vertex_shader() &&
GetDxbcShaderModification().host_vertex_shader_type ==
Shader::HostVertexShaderType::kVertex;
} }
inline bool IsDxbcDomainShader() const { bool IsDxbcDomainShader() const {
return IsDxbcVertexOrDomainShader() && return is_vertex_shader() &&
host_vertex_shader_type() != Shader::HostVertexShaderType::kVertex; GetDxbcShaderModification().host_vertex_shader_type !=
} Shader::HostVertexShaderType::kVertex;
inline bool IsDxbcPixelShader() const {
return is_depth_only_pixel_shader_ || is_pixel_shader();
} }
// Whether to use switch-case rather than if (pc >= label) for control flow. // Whether to use switch-case rather than if (pc >= label) for control flow.
@ -2181,10 +2215,37 @@ class DxbcShaderTranslator : public ShaderTranslator {
uint32_t piece_temp_component, uint32_t accumulator_temp, uint32_t piece_temp_component, uint32_t accumulator_temp,
uint32_t accumulator_temp_component); uint32_t accumulator_temp_component);
// Converts the depth value externally clamped to the representable [0, 2)
// range to 20e4 floating point, with zeros in bits 24:31, rounding to the
// nearest even. Source and destination may be the same, temporary must be
// different than both.
void PreClampedDepthTo20e4(uint32_t d24_temp, uint32_t d24_temp_component,
uint32_t d32_temp, uint32_t d32_temp_component,
uint32_t temp_temp, uint32_t temp_temp_component);
bool IsDepthStencilSystemTempUsed() const {
// See system_temp_depth_stencil_ documentation for explanation of cases.
if (edram_rov_used_) {
return writes_depth() || ROV_IsDepthStencilEarly();
}
return writes_depth() && DSV_IsWritingFloat24Depth();
}
// Whether the current non-ROV pixel shader should convert the depth to 20e4.
bool DSV_IsWritingFloat24Depth() const {
if (edram_rov_used_) {
return false;
}
Modification::DepthStencilMode depth_stencil_mode =
GetDxbcShaderModification().depth_stencil_mode;
return depth_stencil_mode ==
Modification::DepthStencilMode::kFloat24Truncating ||
depth_stencil_mode ==
Modification::DepthStencilMode::kFloat24Rounding;
}
// Whether it's possible and worth skipping running the translated shader for // Whether it's possible and worth skipping running the translated shader for
// 2x2 quads. // 2x2 quads.
bool ROV_IsDepthStencilEarly() const { bool ROV_IsDepthStencilEarly() const {
return !is_depth_only_pixel_shader_ && !writes_depth(); return !is_depth_only_pixel_shader_ && !writes_depth() &&
memexport_stream_constants().empty();
} }
// Converts the depth value to 24-bit (storing the result in bits 0:23 and // Converts the depth value to 24-bit (storing the result in bits 0:23 and
// zeros in 24:31, not creating room for stencil - since this may be involved // zeros in 24:31, not creating room for stencil - since this may be involved
@ -2197,8 +2258,8 @@ class DxbcShaderTranslator : public ShaderTranslator {
// Does all the depth/stencil-related things, including or not including // Does all the depth/stencil-related things, including or not including
// writing based on whether it's late, or on whether it's safe to do it early. // writing based on whether it's late, or on whether it's safe to do it early.
// Updates system_temp_rov_params_ result and coverage if allowed and safe, // Updates system_temp_rov_params_ result and coverage if allowed and safe,
// updates system_temp_rov_depth_stencil_, and if early and the coverage is // updates system_temp_depth_stencil_, and if early and the coverage is empty
// empty for all pixels in the 2x2 quad and safe to return early (stencil is // for all pixels in the 2x2 quad and safe to return early (stencil is
// unchanged or known that it's safe not to await kills/alphatest/AtoC), // unchanged or known that it's safe not to await kills/alphatest/AtoC),
// returns from the shader. // returns from the shader.
void ROV_DepthStencilTest(); void ROV_DepthStencilTest();
@ -2248,6 +2309,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
// Discards the SSAA sample if it's masked out by alpha to coverage. // Discards the SSAA sample if it's masked out by alpha to coverage.
void CompletePixelShader_WriteToRTVs_AlphaToMask(); void CompletePixelShader_WriteToRTVs_AlphaToMask();
void CompletePixelShader_WriteToRTVs(); void CompletePixelShader_WriteToRTVs();
void CompletePixelShader_DSV_DepthTo24Bit();
// Masks the sample away from system_temp_rov_params_.x if it's not covered. // Masks the sample away from system_temp_rov_params_.x if it's not covered.
// threshold_offset and temp.temp_component can be the same if needed. // threshold_offset and temp.temp_component can be the same if needed.
void CompletePixelShader_ROV_AlphaToMaskSample( void CompletePixelShader_ROV_AlphaToMaskSample(
@ -2333,6 +2395,11 @@ class DxbcShaderTranslator : public ShaderTranslator {
xenos::TextureFilter min_filter, xenos::TextureFilter min_filter,
xenos::TextureFilter mip_filter, xenos::TextureFilter mip_filter,
xenos::AnisoFilter aniso_filter); xenos::AnisoFilter aniso_filter);
// Returns the number of texture SRV and sampler offsets that need to be
// passed via a constant buffer to the shader.
uint32_t GetBindlessResourceCount() const {
return uint32_t(texture_bindings_.size() + sampler_bindings_.size());
}
// Marks fetch constants as used by the DXBC shader and returns DxbcSrc // Marks fetch constants as used by the DXBC shader and returns DxbcSrc
// for the words 01 (pair 0), 23 (pair 1) or 45 (pair 2) of the texture fetch // for the words 01 (pair 0), 23 (pair 1) or 45 (pair 2) of the texture fetch
// constant. // constant.
@ -2364,7 +2431,7 @@ class DxbcShaderTranslator : public ShaderTranslator {
static uint32_t AppendString(std::vector<uint32_t>& dest, const char* source); static uint32_t AppendString(std::vector<uint32_t>& dest, const char* source);
// Returns the length of a string as if it was appended to a DWORD stream, in // Returns the length of a string as if it was appended to a DWORD stream, in
// bytes. // bytes.
static inline uint32_t GetStringLength(const char* source) { static uint32_t GetStringLength(const char* source) {
return uint32_t(xe::align(std::strlen(source) + 1, sizeof(uint32_t))); return uint32_t(xe::align(std::strlen(source) + 1, sizeof(uint32_t)));
} }
@ -2479,8 +2546,8 @@ class DxbcShaderTranslator : public ShaderTranslator {
bool in_primitive_id_used_; bool in_primitive_id_used_;
// Whether InOutRegister::kDSInControlPointIndex has been used in the shader. // Whether InOutRegister::kDSInControlPointIndex has been used in the shader.
bool in_control_point_index_used_; bool in_control_point_index_used_;
// Whether the XY of the pixel position has been used in the pixel shader. // Mask of the pixel/sample position actually used in the pixel shader.
bool in_position_xy_used_; uint32_t in_position_used_;
// Whether the faceness has been used in the pixel shader. // Whether the faceness has been used in the pixel shader.
bool in_front_face_used_; bool in_front_face_used_;
@ -2518,15 +2585,14 @@ class DxbcShaderTranslator : public ShaderTranslator {
// W - Base-relative resolution-scaled EDRAM offset for 64bpp color data, in // W - Base-relative resolution-scaled EDRAM offset for 64bpp color data, in
// dwords. // dwords.
uint32_t system_temp_rov_params_; uint32_t system_temp_rov_params_;
// ROV only - new depth/stencil data. 4 VGPRs when not writing to oDepth, 1 // Two purposes:
// VGPR when writing to oDepth. Not used in the depth-only pixel shader (or, // - When writing to oDepth, and either using ROV or converting the depth to
// more formally, if neither early depth-stencil nor oDepth are used) because // float24: X also used to hold the depth written by the shader,
// it always calculates and writes in the same place. // later used as a temporary during depth/stencil testing.
// When not writing to oDepth: New per-sample depth/stencil values, generated // - Otherwise, when using ROV output with ROV_IsDepthStencilEarly being true:
// during early depth/stencil test (actual writing checks coverage bits). // New per-sample depth/stencil values, generated during early depth/stencil
// When writing to oDepth: X also used to hold the depth written by the // test (actual writing checks coverage bits).
// shader, later used as a temporary during depth/stencil testing. uint32_t system_temp_depth_stencil_;
uint32_t system_temp_rov_depth_stencil_;
// Up to 4 color outputs in pixel shaders (because of exponent bias, alpha // Up to 4 color outputs in pixel shaders (because of exponent bias, alpha
// test and remapping, and also for ROV writing). // test and remapping, and also for ROV writing).
uint32_t system_temps_color_[4]; uint32_t system_temps_color_[4];
@ -2587,6 +2653,8 @@ class DxbcShaderTranslator : public ShaderTranslator {
uint32_t srv_index_bindless_textures_3d_; uint32_t srv_index_bindless_textures_3d_;
uint32_t srv_index_bindless_textures_cube_; uint32_t srv_index_bindless_textures_cube_;
// The first binding is at t[SRVMainRegister::kBindfulTexturesStart] of space
// SRVSpace::kMain.
std::vector<TextureBinding> texture_bindings_; std::vector<TextureBinding> texture_bindings_;
std::unordered_map<uint32_t, uint32_t> std::unordered_map<uint32_t, uint32_t>
texture_bindings_for_bindful_srv_indices_; texture_bindings_for_bindful_srv_indices_;

View File

@ -677,7 +677,7 @@ void DxbcShaderTranslator::ProcessTextureFetchInstruction(
// Whether to use gradients (implicit or explicit) for LOD calculation. // Whether to use gradients (implicit or explicit) for LOD calculation.
bool use_computed_lod = bool use_computed_lod =
instr.attributes.use_computed_lod && instr.attributes.use_computed_lod &&
(IsDxbcPixelShader() || instr.attributes.use_register_gradients); (is_pixel_shader() || instr.attributes.use_register_gradients);
if (instr.opcode == FetchOpcode::kGetTextureComputedLod && if (instr.opcode == FetchOpcode::kGetTextureComputedLod &&
(!use_computed_lod || instr.attributes.use_register_gradients)) { (!use_computed_lod || instr.attributes.use_register_gradients)) {
assert_always(); assert_always();

View File

@ -106,7 +106,7 @@ void DxbcShaderTranslator::ExportToMemory() {
kSysConst_Flags_Vec) kSysConst_Flags_Vec)
.Select(kSysConst_Flags_Comp), .Select(kSysConst_Flags_Comp),
DxbcSrc::LU(kSysFlag_SharedMemoryIsUAV)); DxbcSrc::LU(kSysFlag_SharedMemoryIsUAV));
if (IsDxbcPixelShader()) { if (is_pixel_shader()) {
// Disable memexport in pixel shaders with supersampling since VPOS is // Disable memexport in pixel shaders with supersampling since VPOS is
// ambiguous. // ambiguous.
if (edram_rov_used_) { if (edram_rov_used_) {

View File

@ -167,7 +167,7 @@ void DxbcShaderTranslator::StartPixelShader_LoadROVParameters() {
// bigger) to integer to system_temp_rov_params_.zw. // bigger) to integer to system_temp_rov_params_.zw.
// system_temp_rov_params_.z = X host pixel position as uint // system_temp_rov_params_.z = X host pixel position as uint
// system_temp_rov_params_.w = Y host pixel position as uint // system_temp_rov_params_.w = Y host pixel position as uint
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b1100), DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b1100),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition), 0b01000000)); DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition), 0b01000000));
// Revert the resolution scale to convert the position to guest pixels. // Revert the resolution scale to convert the position to guest pixels.
@ -315,7 +315,7 @@ void DxbcShaderTranslator::StartPixelShader_LoadROVParameters() {
// Add host pixel offsets. // Add host pixel offsets.
// system_temp_rov_params_.y = scaled 32bpp depth/stencil address // system_temp_rov_params_.y = scaled 32bpp depth/stencil address
// system_temp_rov_params_.z = scaled 32bpp color offset if needed // system_temp_rov_params_.z = scaled 32bpp color offset if needed
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
for (uint32_t i = 0; i < 2; ++i) { for (uint32_t i = 0; i < 2; ++i) {
// Convert a position component to integer. // Convert a position component to integer.
DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b0001), DxbcOpFToU(DxbcDest::R(system_temp_rov_params_, 0b0001),
@ -417,23 +417,50 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
// With early depth/stencil, depth/stencil writing may be deferred to the // With early depth/stencil, depth/stencil writing may be deferred to the
// end of the shader to prevent writing in case something (like alpha test, // end of the shader to prevent writing in case something (like alpha test,
// which is dynamic GPU state) discards the pixel. So, write directly to the // which is dynamic GPU state) discards the pixel. So, write directly to the
// persistent register, system_temp_rov_depth_stencil_, instead of a local // persistent register, system_temp_depth_stencil_, instead of a local
// temporary register. // temporary register.
DxbcDest sample_depth_stencil_dest( DxbcDest sample_depth_stencil_dest(
depth_stencil_early depth_stencil_early ? DxbcDest::R(system_temp_depth_stencil_, 1 << i)
? DxbcDest::R(system_temp_rov_depth_stencil_, 1 << i) : temp_x_dest);
: temp_x_dest);
DxbcSrc sample_depth_stencil_src( DxbcSrc sample_depth_stencil_src(
depth_stencil_early depth_stencil_early ? DxbcSrc::R(system_temp_depth_stencil_).Select(i)
? DxbcSrc::R(system_temp_rov_depth_stencil_).Select(i) : temp_x_src);
: temp_x_src);
if (!i) { if (!i) {
if (writes_depth()) { if (writes_depth()) {
// Clamp oDepth to the lower viewport depth bound (depth clamp happens
// after the pixel shader in the pipeline, at least on Direct3D 11 and
// Vulkan, thus applies to the shader's depth output too).
system_constants_used_ |= 1ull << kSysConst_EdramDepthRange_Index;
DxbcOpMax(DxbcDest::R(system_temp_depth_stencil_, 0b0001),
DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX),
DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants),
kSysConst_EdramDepthRange_Vec)
.Select(kSysConst_EdramDepthRangeOffset_Comp));
// Calculate the upper Z range bound to temp.x for clamping after
// biasing.
// temp.x = viewport maximum depth
system_constants_used_ |= 1ull << kSysConst_EdramDepthRange_Index;
DxbcOpAdd(temp_x_dest,
DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants),
kSysConst_EdramDepthRange_Vec)
.Select(kSysConst_EdramDepthRangeOffset_Comp),
DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants),
kSysConst_EdramDepthRange_Vec)
.Select(kSysConst_EdramDepthRangeScale_Comp));
// Clamp oDepth to the upper viewport depth bound (already not above 1,
// but saturate for total safety).
// temp.x = free
DxbcOpMin(DxbcDest::R(system_temp_depth_stencil_, 0b0001),
DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX),
temp_x_src, true);
// Convert the shader-generated depth to 24-bit, using temp.x as // Convert the shader-generated depth to 24-bit, using temp.x as
// temporary. // temporary.
ROV_DepthTo24Bit(system_temp_rov_depth_stencil_, 0, ROV_DepthTo24Bit(system_temp_depth_stencil_, 0,
system_temp_rov_depth_stencil_, 0, temp, 0); system_temp_depth_stencil_, 0, temp, 0);
} else { } else {
// Load the first sample's Z*W and W to temp.xy - need this regardless // Load the first sample's Z*W and W to temp.xy - need this regardless
// of coverage for polygon offset. // of coverage for polygon offset.
@ -529,14 +556,14 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
} }
// Get if the current sample is covered to temp.w. // Get if the current sample is covered to temp.w.
// temp.x = first sample's viewport space Z or 24-bit oDepth // temp.x = first sample's viewport space Z if not writing to oDepth
// temp.y = polygon offset if not writing to oDepth // temp.y = polygon offset if not writing to oDepth
// temp.z = viewport maximum depth if not writing to oDepth // temp.z = viewport maximum depth if not writing to oDepth
// temp.w = coverage of the current sample // temp.w = coverage of the current sample
DxbcOpAnd(temp_w_dest, DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kXXXX), DxbcOpAnd(temp_w_dest, DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kXXXX),
DxbcSrc::LU(1 << i)); DxbcSrc::LU(1 << i));
// Check if the current sample is covered. Release 1 VGPR. // Check if the current sample is covered. Release 1 VGPR.
// temp.x = first sample's viewport space Z or 24-bit oDepth // temp.x = first sample's viewport space Z if not writing to oDepth
// temp.y = polygon offset if not writing to oDepth // temp.y = polygon offset if not writing to oDepth
// temp.z = viewport maximum depth if not writing to oDepth // temp.z = viewport maximum depth if not writing to oDepth
// temp.w = free // temp.w = free
@ -546,7 +573,7 @@ void DxbcShaderTranslator::ROV_DepthStencilTest() {
// Copy the 24-bit depth common to all samples to sample_depth_stencil. // Copy the 24-bit depth common to all samples to sample_depth_stencil.
// temp.x = shader-generated 24-bit depth // temp.x = shader-generated 24-bit depth
DxbcOpMov(sample_depth_stencil_dest, DxbcOpMov(sample_depth_stencil_dest,
DxbcSrc::R(system_temp_rov_depth_stencil_, DxbcSrc::kXXXX)); DxbcSrc::R(system_temp_depth_stencil_, DxbcSrc::kXXXX));
} else { } else {
if (i) { if (i) {
// Sample's depth precalculated for sample 0 (for slope-scaled depth // Sample's depth precalculated for sample 0 (for slope-scaled depth
@ -1720,7 +1747,7 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToRTVs_AlphaToMask() {
// Convert SSAA sample position to integer to temp.xy (not caring about the // Convert SSAA sample position to integer to temp.xy (not caring about the
// resolution scale because it's not supported anywhere on the RTV output // resolution scale because it's not supported anywhere on the RTV output
// path). // path).
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
DxbcOpFToU(DxbcDest::R(temp, 0b0011), DxbcOpFToU(DxbcDest::R(temp, 0b0011),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition))); DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
@ -1913,6 +1940,139 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToRTVs() {
PopSystemTemp(2); PopSystemTemp(2);
} }
void DxbcShaderTranslator::CompletePixelShader_DSV_DepthTo24Bit() {
if (!DSV_IsWritingFloat24Depth()) {
return;
}
uint32_t temp;
if (writes_depth()) {
// The depth is already written to system_temp_depth_stencil_.x and clamped
// to 0...1 with NaNs dropped (saturating in StoreResult); yzw are free.
temp = system_temp_depth_stencil_;
} else {
// Need a temporary variable; copy the sample's depth input to it and
// saturate it (in Direct3D 11, depth is clamped to the viewport bounds
// after the pixel shader, and SV_Position.z contains the unclamped depth,
// which may be outside the viewport's depth range if it's biased); though
// it will be clamped to the viewport bounds anyway, but to be able to make
// the assumption of it being clamped while working with the bit
// representation.
temp = PushSystemTemp();
in_position_used_ |= 0b0100;
DxbcOpMov(
DxbcDest::R(temp, 0b0001),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition), DxbcSrc::kZZZZ),
true);
}
DxbcDest temp_x_dest(DxbcDest::R(temp, 0b0001));
DxbcSrc temp_x_src(DxbcSrc::R(temp, DxbcSrc::kXXXX));
DxbcDest temp_y_dest(DxbcDest::R(temp, 0b0010));
DxbcSrc temp_y_src(DxbcSrc::R(temp, DxbcSrc::kYYYY));
if (GetDxbcShaderModification().depth_stencil_mode ==
Modification::DepthStencilMode::kFloat24Truncating) {
// Simplified conversion, always less than or equal to the original value -
// just drop the lower bits.
// The float32 exponent bias is 127.
// After saturating, the exponent range is -127...0.
// The smallest normalized 20e4 exponent is -14 - should drop 3 mantissa
// bits at -14 or above.
// The smallest denormalized 20e4 number is -34 - should drop 23 mantissa
// bits at -34.
// Anything smaller than 2^-34 becomes 0.
DxbcDest truncate_dest(writes_depth() ? DxbcDest::ODepth()
: DxbcDest::ODepthLE());
// Check if the number is representable as a float24 after truncation - the
// exponent is at least -34.
DxbcOpUGE(temp_y_dest, temp_x_src, DxbcSrc::LU(0x2E800000));
DxbcOpIf(true, temp_y_src);
{
// Extract the biased float32 exponent to temp.y.
// temp.y = 113+ at exponent -14+.
// temp.y = 93 at exponent -34.
DxbcOpUBFE(temp_y_dest, DxbcSrc::LU(8), DxbcSrc::LU(23), temp_x_src);
// Convert exponent to the unclamped number of bits to truncate.
// 116 - 113 = 3.
// 116 - 93 = 23.
// temp.y = 3+ at exponent -14+.
// temp.y = 23 at exponent -34.
DxbcOpIAdd(temp_y_dest, DxbcSrc::LI(116), -temp_y_src);
// Clamp the truncated bit count to drop 3 bits of any normal number.
// Exponents below -34 are handled separately.
// temp.y = 3 at exponent -14.
// temp.y = 23 at exponent -34.
DxbcOpIMax(temp_y_dest, temp_y_src, DxbcSrc::LI(3));
// Truncate the mantissa - fill the low bits with zeros.
DxbcOpBFI(truncate_dest, temp_y_src, DxbcSrc::LU(0), DxbcSrc::LU(0),
temp_x_src);
}
// The number is not representable as float24 after truncation - zero.
DxbcOpElse();
DxbcOpMov(truncate_dest, DxbcSrc::LF(0.0f));
// Close the non-zero result check.
DxbcOpEndIf();
} else {
// Properly convert to 20e4, with rounding to the nearest even.
PreClampedDepthTo20e4(temp, 0, temp, 0, temp, 1);
// Convert back to float32.
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// Unpack the exponent to temp.y.
DxbcOpUShR(temp_y_dest, temp_x_src, DxbcSrc::LU(20));
// Unpack the mantissa to temp.x.
DxbcOpAnd(temp_x_dest, temp_x_src, DxbcSrc::LU(0xFFFFF));
// Check if the number is denormalized.
DxbcOpIf(false, temp_y_src);
{
// Check if the number is non-zero (if the mantissa isn't zero - the
// exponent is known to be zero at this point).
DxbcOpIf(true, temp_x_src);
{
// Normalize the mantissa.
// Note that HLSL firstbithigh(x) is compiled to DXBC like:
// `x ? 31 - firstbit_hi(x) : -1`
// (returns the index from the LSB, not the MSB, but -1 for zero too).
// temp.y = firstbit_hi(mantissa)
DxbcOpFirstBitHi(temp_y_dest, temp_x_src);
// temp.y = 20 - firstbithigh(mantissa)
// Or:
// temp.y = 20 - (31 - firstbit_hi(mantissa))
DxbcOpIAdd(temp_y_dest, temp_y_src, DxbcSrc::LI(20 - 31));
// mantissa = mantissa << (20 - firstbithigh(mantissa))
// AND 0xFFFFF not needed after this - BFI will do it.
DxbcOpIShL(temp_x_dest, temp_x_src, temp_y_src);
// Get the normalized exponent.
// exponent = 1 - (20 - firstbithigh(mantissa))
DxbcOpIAdd(temp_y_dest, DxbcSrc::LI(1), -temp_y_src);
}
// The number is zero.
DxbcOpElse();
{
// Set the unbiased exponent to -112 for zero - 112 will be added later,
// resulting in zero float32.
DxbcOpMov(temp_y_dest, DxbcSrc::LI(-112));
}
// Close the non-zero check.
DxbcOpEndIf();
}
// Close the denormal check.
DxbcOpEndIf();
// Bias the exponent and move it to the correct location in float32 to
// temp.y.
DxbcOpIMAd(temp_y_dest, temp_y_src, DxbcSrc::LI(1 << 23),
DxbcSrc::LI(112 << 23));
// Combine the mantissa and the exponent into the result.
DxbcOpBFI(DxbcDest::ODepth(), DxbcSrc::LU(20), DxbcSrc::LU(3), temp_x_src,
temp_y_src);
}
if (!writes_depth()) {
// Release temp.
PopSystemTemp();
}
}
void DxbcShaderTranslator::CompletePixelShader_ROV_AlphaToMaskSample( void DxbcShaderTranslator::CompletePixelShader_ROV_AlphaToMaskSample(
uint32_t sample_index, float threshold_base, DxbcSrc threshold_offset, uint32_t sample_index, float threshold_base, DxbcSrc threshold_offset,
float threshold_offset_scale, uint32_t temp, uint32_t temp_component) { float threshold_offset_scale, uint32_t temp, uint32_t temp_component) {
@ -1957,7 +2117,7 @@ void DxbcShaderTranslator::CompletePixelShader_ROV_AlphaToMask() {
// floating-point. With resolution scaling, still using host pixels, to // floating-point. With resolution scaling, still using host pixels, to
// preserve the idea of dithering. // preserve the idea of dithering.
// temp.x = alpha to coverage offset as float 0.0...3.0. // temp.x = alpha to coverage offset as float 0.0...3.0.
in_position_xy_used_ = true; in_position_used_ |= 0b0011;
DxbcOpFToU(DxbcDest::R(temp, 0b0011), DxbcOpFToU(DxbcDest::R(temp, 0b0011),
DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition))); DxbcSrc::V(uint32_t(InOutRegister::kPSInPosition)));
DxbcOpAnd(DxbcDest::R(temp, 0b0010), DxbcSrc::R(temp, DxbcSrc::kYYYY), DxbcOpAnd(DxbcDest::R(temp, 0b0010), DxbcSrc::R(temp, DxbcSrc::kYYYY),
@ -2067,7 +2227,7 @@ void DxbcShaderTranslator::CompletePixelShader_WriteToROV() {
DxbcOpStoreUAVTyped( DxbcOpStoreUAVTyped(
DxbcDest::U(uav_index_edram_, uint32_t(UAVRegister::kEdram)), DxbcDest::U(uav_index_edram_, uint32_t(UAVRegister::kEdram)),
DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kYYYY), 1, DxbcSrc::R(system_temp_rov_params_, DxbcSrc::kYYYY), 1,
DxbcSrc::R(system_temp_rov_depth_stencil_).Select(i)); DxbcSrc::R(system_temp_depth_stencil_).Select(i));
} }
// Close the write check. // Close the write check.
DxbcOpEndIf(); DxbcOpEndIf();
@ -3059,15 +3219,16 @@ void DxbcShaderTranslator::CompletePixelShader() {
CompletePixelShader_WriteToROV(); CompletePixelShader_WriteToROV();
} else { } else {
CompletePixelShader_WriteToRTVs(); CompletePixelShader_WriteToRTVs();
CompletePixelShader_DSV_DepthTo24Bit();
} }
} }
void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp, void DxbcShaderTranslator::PreClampedDepthTo20e4(uint32_t d24_temp,
uint32_t d24_temp_component, uint32_t d24_temp_component,
uint32_t d32_temp, uint32_t d32_temp,
uint32_t d32_temp_component, uint32_t d32_temp_component,
uint32_t temp_temp, uint32_t temp_temp,
uint32_t temp_temp_component) { uint32_t temp_temp_component) {
assert_true(temp_temp != d24_temp || assert_true(temp_temp != d24_temp ||
temp_temp_component != d24_temp_component); temp_temp_component != d24_temp_component);
assert_true(temp_temp != d32_temp || assert_true(temp_temp != d32_temp ||
@ -3079,68 +3240,83 @@ void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp,
DxbcDest temp_dest(DxbcDest::R(temp_temp, 1 << temp_temp_component)); DxbcDest temp_dest(DxbcDest::R(temp_temp, 1 << temp_temp_component));
DxbcSrc temp_src(DxbcSrc::R(temp_temp).Select(temp_temp_component)); DxbcSrc temp_src(DxbcSrc::R(temp_temp).Select(temp_temp_component));
// CFloat24 from d3dref9.dll.
// Assuming the depth is already clamped to [0, 2) (in all places, the depth
// is written with the saturate flag set).
// Check if the number is too small to be represented as normalized 20e4.
// temp = f32 < 2^-14
DxbcOpULT(temp_dest, d32_src, DxbcSrc::LU(0x38800000));
// Handle denormalized numbers separately.
DxbcOpIf(true, temp_src);
{
// temp = f32 >> 23
DxbcOpUShR(temp_dest, d32_src, DxbcSrc::LU(23));
// temp = 113 - (f32 >> 23)
DxbcOpIAdd(temp_dest, DxbcSrc::LI(113), -temp_src);
// Don't allow the shift to overflow, since in DXBC the lower 5 bits of the
// shift amount are used (otherwise 0 becomes 8).
// temp = min(113 - (f32 >> 23), 24)
DxbcOpUMin(temp_dest, temp_src, DxbcSrc::LU(24));
// biased_f32 = (f32 & 0x7FFFFF) | 0x800000
DxbcOpBFI(d24_dest, DxbcSrc::LU(9), DxbcSrc::LU(23), DxbcSrc::LU(1),
d32_src);
// biased_f32 = ((f32 & 0x7FFFFF) | 0x800000) >> min(113 - (f32 >> 23), 24)
DxbcOpUShR(d24_dest, d24_src, temp_src);
}
// Not denormalized?
DxbcOpElse();
{
// Bias the exponent.
// biased_f32 = f32 + (-112 << 23)
// (left shift of a negative value is undefined behavior)
DxbcOpIAdd(d24_dest, d32_src, DxbcSrc::LU(0xC8000000u));
}
// Close the denormal check.
DxbcOpEndIf();
// Build the 20e4 number.
// temp = (biased_f32 >> 3) & 1
DxbcOpUBFE(temp_dest, DxbcSrc::LU(1), DxbcSrc::LU(3), d24_src);
// f24 = biased_f32 + 3
DxbcOpIAdd(d24_dest, d24_src, DxbcSrc::LU(3));
// f24 = biased_f32 + 3 + ((biased_f32 >> 3) & 1)
DxbcOpIAdd(d24_dest, d24_src, temp_src);
// f24 = ((biased_f32 + 3 + ((biased_f32 >> 3) & 1)) >> 3) & 0xFFFFFF
DxbcOpUBFE(d24_dest, DxbcSrc::LU(24), DxbcSrc::LU(3), d24_src);
}
void DxbcShaderTranslator::ROV_DepthTo24Bit(uint32_t d24_temp,
uint32_t d24_temp_component,
uint32_t d32_temp,
uint32_t d32_temp_component,
uint32_t temp_temp,
uint32_t temp_temp_component) {
assert_true(temp_temp != d32_temp ||
temp_temp_component != d32_temp_component);
// Source and destination may be the same.
system_constants_used_ |= 1ull << kSysConst_Flags_Index; system_constants_used_ |= 1ull << kSysConst_Flags_Index;
DxbcOpAnd(temp_dest, DxbcOpAnd(DxbcDest::R(temp_temp, 1 << temp_temp_component),
DxbcSrc::CB(cbuffer_index_system_constants_, DxbcSrc::CB(cbuffer_index_system_constants_,
uint32_t(CbufferRegister::kSystemConstants), uint32_t(CbufferRegister::kSystemConstants),
kSysConst_Flags_Vec) kSysConst_Flags_Vec)
.Select(kSysConst_Flags_Comp), .Select(kSysConst_Flags_Comp),
DxbcSrc::LU(kSysFlag_ROVDepthFloat24)); DxbcSrc::LU(kSysFlag_ROVDepthFloat24));
// Convert according to the format. // Convert according to the format.
DxbcOpIf(true, temp_src); DxbcOpIf(true, DxbcSrc::R(temp_temp).Select(temp_temp_component));
{ {
// 20e4 conversion, using 1 VGPR. // 20e4 conversion.
// CFloat24 from d3dref9.dll. PreClampedDepthTo20e4(d24_temp, d24_temp_component, d32_temp,
// Assuming the depth is already clamped to [0, 2) (in all places, the depth d32_temp_component, temp_temp, temp_temp_component);
// is written with the saturate flag set).
// Check if the number is too small to be represented as normalized 20e4.
// temp = f32 < 2^-14
DxbcOpULT(temp_dest, d32_src, DxbcSrc::LU(0x38800000));
// Handle denormalized numbers separately.
DxbcOpIf(true, temp_src);
{
// temp = f32 >> 23
DxbcOpUShR(temp_dest, d32_src, DxbcSrc::LU(23));
// temp = 113 - (f32 >> 23)
DxbcOpIAdd(temp_dest, DxbcSrc::LI(113), -temp_src);
// Don't allow the shift to overflow, since in DXBC the lower 5 bits of
// the shift amount are used (otherwise 0 becomes 8).
// temp = min(113 - (f32 >> 23), 24)
DxbcOpUMin(temp_dest, temp_src, DxbcSrc::LU(24));
// biased_f32 = (f32 & 0x7FFFFF) | 0x800000
DxbcOpBFI(d24_dest, DxbcSrc::LU(9), DxbcSrc::LU(23), DxbcSrc::LU(1),
d32_src);
// biased_f32 =
// ((f32 & 0x7FFFFF) | 0x800000) >> min(113 - (f32 >> 23), 24)
DxbcOpUShR(d24_dest, d24_src, temp_src);
}
// Not denormalized?
DxbcOpElse();
{
// Bias the exponent.
// biased_f32 = f32 + (-112 << 23)
// (left shift of a negative value is undefined behavior)
DxbcOpIAdd(d24_dest, d32_src, DxbcSrc::LU(0xC8000000u));
}
// Close the denormal check.
DxbcOpEndIf();
// Build the 20e4 number.
// temp = (biased_f32 >> 3) & 1
DxbcOpUBFE(temp_dest, DxbcSrc::LU(1), DxbcSrc::LU(3), d24_src);
// f24 = biased_f32 + 3
DxbcOpIAdd(d24_dest, d24_src, DxbcSrc::LU(3));
// f24 = biased_f32 + 3 + ((biased_f32 >> 3) & 1)
DxbcOpIAdd(d24_dest, d24_src, temp_src);
// f24 = ((biased_f32 + 3 + ((biased_f32 >> 3) & 1)) >> 3) & 0xFFFFFF
DxbcOpUBFE(d24_dest, DxbcSrc::LU(24), DxbcSrc::LU(3), d24_src);
} }
DxbcOpElse(); DxbcOpElse();
{ {
// Unorm24 conversion. // Unorm24 conversion.
DxbcDest d24_dest(DxbcDest::R(d24_temp, 1 << d24_temp_component));
DxbcSrc d24_src(DxbcSrc::R(d24_temp).Select(d24_temp_component));
// Multiply by float(0xFFFFFF). // Multiply by float(0xFFFFFF).
DxbcOpMul(d24_dest, d32_src, DxbcSrc::LF(16777215.0f)); DxbcOpMul(d24_dest, DxbcSrc::R(d32_temp).Select(d32_temp_component),
DxbcSrc::LF(16777215.0f));
// Round to the nearest even integer. This seems to be the correct way: // Round to the nearest even integer. This seems to be the correct way:
// rounding towards zero gives 0xFF instead of 0x100 in clear shaders in, // rounding towards zero gives 0xFF instead of 0x100 in clear shaders in,
// for instance, Halo 3, but other clear shaders in it are also broken if // for instance, Halo 3, but other clear shaders in it are also broken if

View File

@ -40,9 +40,63 @@ DEFINE_bool(
"be fully covered when MSAA is used with fullscreen passes.", "be fully covered when MSAA is used with fullscreen passes.",
"GPU"); "GPU");
DEFINE_string(
depth_float24_conversion, "",
"Method for converting 32-bit Z values to 20e4 floating point when using "
"host depth buffers without native 20e4 support (when not using rasterizer-"
"ordered views / fragment shader interlocks to perform depth testing "
"manually).\n"
"Use: [any, on_copy, truncate, round]\n"
" on_copy:\n"
" Do depth testing at host precision, converting when copying between "
"host depth buffers and the EDRAM buffer to support reinterpretation, "
"maintaining two copies, in both host and 20e4 formats, for reloading data "
"to host depth buffers when it wasn't overwritten.\n"
" + Highest performance, allows early depth test and writing.\n"
" + Host MSAA is possible with pixel-rate shading where supported.\n"
" - EDRAM > RAM > EDRAM depth buffer round trip done in certain games "
"(such as GTA IV) destroys precision irreparably, causing artifacts if "
"another rendering pass is done after the EDRAM reupload.\n"
" truncate:\n"
" Convert to 20e4 directly in pixel shaders, always rounding down.\n"
" + Good performance, conservative early depth test is possible.\n"
" + No precision loss when anything changes in the storage of the depth "
"buffer, EDRAM > RAM > EDRAM copying preserves precision.\n"
" - Rounding mode is incorrect, sometimes giving results smaller than "
"they should be - may cause inaccuracy especially in edge cases when the "
"game wants to write an exact value.\n"
" - Host MSAA is only possible at SSAA speed, with per-sample shading.\n"
" round:\n"
" Convert to 20e4 directly in pixel shaders, correctly rounding to the "
"nearest even.\n"
" + Highest accuracy.\n"
" - Significantly limited performance, early depth test is not possible.\n"
" - Host MSAA is only possible at SSAA speed, with per-sample shading.\n"
" Any other value:\n"
" Choose what is considered the most optimal (currently \"on_copy\").",
"GPU");
DEFINE_int32(query_occlusion_fake_sample_count, 1000, DEFINE_int32(query_occlusion_fake_sample_count, 1000,
"If set to -1 no sample counts are written, games may hang. Else, " "If set to -1 no sample counts are written, games may hang. Else, "
"the sample count of every tile will be incremented on every " "the sample count of every tile will be incremented on every "
"EVENT_WRITE_ZPD by this number. Setting this to 0 means " "EVENT_WRITE_ZPD by this number. Setting this to 0 means "
"everything is reported as occluded.", "everything is reported as occluded.",
"GPU"); "GPU");
namespace xe {
namespace gpu {
namespace flags {
DepthFloat24Conversion GetDepthFloat24Conversion() {
if (cvars::depth_float24_conversion == "truncate") {
return DepthFloat24Conversion::kOnOutputTruncating;
}
if (cvars::depth_float24_conversion == "round") {
return DepthFloat24Conversion::kOnOutputRounding;
}
return DepthFloat24Conversion::kOnCopy;
}
} // namespace flags
} // namespace gpu
} // namespace xe

View File

@ -22,6 +22,69 @@ DECLARE_bool(gpu_allow_invalid_fetch_constants);
DECLARE_bool(half_pixel_offset); DECLARE_bool(half_pixel_offset);
DECLARE_string(depth_float24_conversion);
DECLARE_int32(query_occlusion_fake_sample_count); DECLARE_int32(query_occlusion_fake_sample_count);
namespace xe {
namespace gpu {
namespace flags {
enum class DepthFloat24Conversion {
// Doing depth test at the host precision, converting to 20e4 to support
// reinterpretation, but keeping a separate EDRAM view containing depth values
// in the host format. When copying from the EDRAM buffer to host depth
// buffers, writing the stored host pixel if stored_f24 == to_f24(stored_host)
// (otherwise it was overwritten by something else, like clearing, or a color
// buffer; this is inexact though, and will incorrectly load pixels that were
// overwritten by something else in the EDRAM, but turned out to have the same
// value on the guest as before - an outdated host-precision value will be
// loaded in these cases instead).
//
// EDRAM > RAM, then reusing the EDRAM region for something else > EDRAM round
// trip destroys precision beyond repair.
//
// Full host early Z and MSAA with pixel-rate shading are supported.
kOnCopy,
// Converting the depth to the closest host value representable exactly as a
// 20e4 float in pixel shaders, to support invariance in cases when the guest
// reuploads a previously resolved depth buffer to the EDRAM, rounding towards
// zero (which contradicts the rounding used by the Direct3D 9 reference
// rasterizer, but allows less-than-or-equal pixel shader depth output to be
// used to preserve most of early Z culling when the game is using reversed
// depth, which is the usual way of doing depth testing on the Xbox 360 and of
// utilizing the advantages of a floating-point encoding).
//
// With MSAA, pixel shaders must run at sample frequency - otherwise, if the
// depth is the same for the entire pixel, intersections of polygons cannot be
// antialiased.
//
// Important usage note: When using this mode, bounds of the fixed-function
// viewport must be converted to and back from float24 too (preferably using
// correct rounding to the nearest even, to reduce the error already caused by
// truncation rather than to amplify it). This ensures that clamping to the
// viewport bounds, which happens after the pixel shader even if it overwrites
// the resulting depth, is never done to a value not representable as float24
// (for example, if the minimum Z is a number too small to be represented as
// float24, but not zero, it won't be possible to write what should become
// 0x000000 to the depth buffer). Note that this may add some error to the
// depth values from the rasterizer; however, modifying Z in the vertex shader
// to make interpolated depth values would cause clipping to be done to
// different bounds, which may be more undesirable, especially in cases when Z
// is explicitly set to a value like 0 or W (in such cases, the adjusted
// polygon may go outside 0...W in clip space and disappear).
kOnOutputTruncating,
// Similar to kOnOutputTruncating, but rounding to the nearest even, more
// correctly, however, because the resulting depth can be bigger than the
// original host value, early depth testing can't be used at all. Same
// viewport usage rules apply.
kOnOutputRounding,
};
DepthFloat24Conversion GetDepthFloat24Conversion();
} // namespace flags
} // namespace gpu
} // namespace xe
#endif // XENIA_GPU_GPU_FLAGS_H_ #endif // XENIA_GPU_GPU_FLAGS_H_

View File

@ -276,8 +276,7 @@ void GraphicsSystem::ClearCaches() {
} }
void GraphicsSystem::InitializeShaderStorage( void GraphicsSystem::InitializeShaderStorage(
const std::filesystem::path& storage_root, uint32_t title_id, const std::filesystem::path& cache_root, uint32_t title_id, bool blocking) {
bool blocking) {
if (!cvars::store_shaders) { if (!cvars::store_shaders) {
return; return;
} }
@ -285,21 +284,18 @@ void GraphicsSystem::InitializeShaderStorage(
if (command_processor_->is_paused()) { if (command_processor_->is_paused()) {
// Safe to run on any thread while the command processor is paused, no // Safe to run on any thread while the command processor is paused, no
// race condition. // race condition.
command_processor_->InitializeShaderStorage(storage_root, title_id, true); command_processor_->InitializeShaderStorage(cache_root, title_id, true);
} else { } else {
xe::threading::Fence fence; xe::threading::Fence fence;
command_processor_->CallInThread( command_processor_->CallInThread([this, cache_root, title_id, &fence]() {
[this, storage_root, title_id, &fence]() { command_processor_->InitializeShaderStorage(cache_root, title_id, true);
command_processor_->InitializeShaderStorage(storage_root, title_id, fence.Signal();
true); });
fence.Signal();
});
fence.Wait(); fence.Wait();
} }
} else { } else {
command_processor_->CallInThread([this, storage_root, title_id]() { command_processor_->CallInThread([this, cache_root, title_id]() {
command_processor_->InitializeShaderStorage(storage_root, title_id, command_processor_->InitializeShaderStorage(cache_root, title_id, false);
false);
}); });
} }
} }

View File

@ -63,7 +63,7 @@ class GraphicsSystem {
virtual void ClearCaches(); virtual void ClearCaches();
void InitializeShaderStorage(const std::filesystem::path& storage_root, void InitializeShaderStorage(const std::filesystem::path& cache_root,
uint32_t title_id, bool blocking); uint32_t title_id, bool blocking);
void RequestFrameTrace(); void RequestFrameTrace();

View File

@ -31,9 +31,13 @@ Shader::Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
xe::copy_and_swap(ucode_data_.data(), ucode_dwords, ucode_dword_count); xe::copy_and_swap(ucode_data_.data(), ucode_dwords, ucode_dword_count);
} }
Shader::~Shader() = default; Shader::~Shader() {
for (auto it : translations_) {
delete it.second;
}
}
std::string Shader::GetTranslatedBinaryString() const { std::string Shader::Translation::GetTranslatedBinaryString() const {
std::string result; std::string result;
result.resize(translated_binary_.size()); result.resize(translated_binary_.size());
std::memcpy(const_cast<char*>(result.data()), translated_binary_.data(), std::memcpy(const_cast<char*>(result.data()), translated_binary_.data(),
@ -41,36 +45,24 @@ std::string Shader::GetTranslatedBinaryString() const {
return result; return result;
} }
std::pair<std::filesystem::path, std::filesystem::path> Shader::Dump( std::filesystem::path Shader::Translation::Dump(
const std::filesystem::path& base_path, const char* path_prefix) { const std::filesystem::path& base_path, const char* path_prefix) {
std::filesystem::path path = base_path;
// Ensure target path exists. // Ensure target path exists.
auto target_path = base_path; if (!path.empty()) {
if (!target_path.empty()) { path = std::filesystem::absolute(path);
target_path = std::filesystem::absolute(target_path); std::filesystem::create_directories(path);
std::filesystem::create_directories(target_path);
} }
path = path /
auto base_name = fmt::format(
fmt::format("shader_{}_{:016X}", path_prefix, ucode_data_hash_); "shader_{:016X}_{:08X}.{}.{}", shader().ucode_data_hash(),
modification(), path_prefix,
std::string txt_name, bin_name; shader().type() == xenos::ShaderType::kVertex ? "vert" : "frag");
if (shader_type_ == xenos::ShaderType::kVertex) { FILE* f = filesystem::OpenFile(path, "wb");
txt_name = base_name + ".vert";
bin_name = base_name + ".bin.vert";
} else {
txt_name = base_name + ".frag";
bin_name = base_name + ".bin.frag";
}
std::filesystem::path txt_path, bin_path;
txt_path = base_path / txt_name;
bin_path = base_path / bin_name;
FILE* f = filesystem::OpenFile(txt_path, "wb");
if (f) { if (f) {
fwrite(translated_binary_.data(), 1, translated_binary_.size(), f); fwrite(translated_binary_.data(), 1, translated_binary_.size(), f);
fprintf(f, "\n\n"); fprintf(f, "\n\n");
auto ucode_disasm_ptr = ucode_disassembly().c_str(); auto ucode_disasm_ptr = shader().ucode_disassembly().c_str();
while (*ucode_disasm_ptr) { while (*ucode_disasm_ptr) {
auto line_end = std::strchr(ucode_disasm_ptr, '\n'); auto line_end = std::strchr(ucode_disasm_ptr, '\n');
fprintf(f, "// "); fprintf(f, "// ");
@ -83,14 +75,58 @@ std::pair<std::filesystem::path, std::filesystem::path> Shader::Dump(
} }
fclose(f); fclose(f);
} }
return std::move(path);
}
f = filesystem::OpenFile(bin_path, "wb"); Shader::Translation* Shader::GetOrCreateTranslation(uint32_t modification,
bool* is_new) {
auto it = translations_.find(modification);
if (it != translations_.end()) {
if (is_new) {
*is_new = false;
}
return it->second;
}
Translation* translation = CreateTranslationInstance(modification);
translations_.emplace(modification, translation);
if (is_new) {
*is_new = true;
}
return translation;
}
void Shader::DestroyTranslation(uint32_t modification) {
auto it = translations_.find(modification);
if (it == translations_.end()) {
return;
}
delete it->second;
translations_.erase(it);
}
std::filesystem::path Shader::DumpUcodeBinary(
const std::filesystem::path& base_path) {
// Ensure target path exists.
std::filesystem::path path = base_path;
if (!path.empty()) {
path = std::filesystem::absolute(path);
std::filesystem::create_directories(path);
}
path = path /
fmt::format("shader_{:016X}.ucode.bin.{}", ucode_data_hash(),
type() == xenos::ShaderType::kVertex ? "vert" : "frag");
FILE* f = filesystem::OpenFile(path, "wb");
if (f) { if (f) {
fwrite(ucode_data_.data(), 4, ucode_data_.size(), f); fwrite(ucode_data().data(), 4, ucode_data().size(), f);
fclose(f); fclose(f);
} }
return std::move(path);
}
return {std::move(txt_path), std::move(bin_path)}; Shader::Translation* Shader::CreateTranslationInstance(uint32_t modification) {
// Default implementation for simple cases like ucode disassembly.
return new Translation(*this, modification);
} }
} // namespace gpu } // namespace gpu

View File

@ -11,8 +11,12 @@
#define XENIA_GPU_SHADER_H_ #define XENIA_GPU_SHADER_H_
#include <algorithm> #include <algorithm>
#include <atomic>
#include <cstdint>
#include <filesystem> #include <filesystem>
#include <string> #include <string>
#include <unordered_map>
#include <utility>
#include <vector> #include <vector>
#include "xenia/base/math.h" #include "xenia/base/math.h"
@ -591,6 +595,8 @@ struct ParsedAluInstruction {
class Shader { class Shader {
public: public:
// Type of the vertex shader in a D3D11-like rendering pipeline - shader
// interface depends on in, so it must be known at translation time.
// If values are changed, INVALIDATE SHADER STORAGES (increase their version // If values are changed, INVALIDATE SHADER STORAGES (increase their version
// constexpr) where those are stored! And check bit count where this is // constexpr) where those are stored! And check bit count where this is
// packed. This is : uint32_t for simplicity of packing in bit fields. // packed. This is : uint32_t for simplicity of packing in bit fields.
@ -603,6 +609,8 @@ class Shader {
kQuadDomainCPIndexed, kQuadDomainCPIndexed,
kQuadDomainPatchIndexed, kQuadDomainPatchIndexed,
}; };
// For packing HostVertexShaderType in bit fields.
static constexpr uint32_t kHostVertexShaderTypeBitCount = 3;
struct Error { struct Error {
bool is_fatal = false; bool is_fatal = false;
@ -683,6 +691,67 @@ class Shader {
} }
}; };
class Translation {
public:
virtual ~Translation() {}
Shader& shader() const { return shader_; }
// Translator-specific modification bits.
uint32_t modification() const { return modification_; }
// True if the shader was translated and prepared without error.
bool is_valid() const { return is_valid_; }
// True if the shader has already been translated.
bool is_translated() const { return is_translated_; }
// Errors that occurred during translation.
const std::vector<Error>& errors() const { return errors_; }
// Translated shader binary (or text).
const std::vector<uint8_t>& translated_binary() const {
return translated_binary_;
}
// Gets the translated shader binary as a string.
// This is only valid if it is actually text.
std::string GetTranslatedBinaryString() const;
// Disassembly of the translated from the host graphics layer.
// May be empty if the host does not support disassembly.
const std::string& host_disassembly() const { return host_disassembly_; }
// In case disassembly depends on the GPU backend, for setting it
// externally.
void set_host_disassembly(std::string disassembly) {
host_disassembly_ = std::move(disassembly);
}
// For dumping after translation. Dumps the shader's disassembled microcode,
// translated code, and, if available, translated disassembly, to a file in
// the given path based on ucode hash. Returns the name of the written file.
std::filesystem::path Dump(const std::filesystem::path& base_path,
const char* path_prefix);
protected:
Translation(Shader& shader, uint32_t modification)
: shader_(shader), modification_(modification) {}
private:
friend class Shader;
friend class ShaderTranslator;
Shader& shader_;
uint32_t modification_;
bool is_valid_ = false;
bool is_translated_ = false;
std::vector<Error> errors_;
std::vector<uint8_t> translated_binary_;
std::string host_disassembly_;
};
Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash, Shader(xenos::ShaderType shader_type, uint64_t ucode_data_hash,
const uint32_t* ucode_dwords, size_t ucode_dword_count); const uint32_t* ucode_dwords, size_t ucode_dword_count);
virtual ~Shader(); virtual ~Shader();
@ -690,19 +759,30 @@ class Shader {
// Whether the shader is identified as a vertex or pixel shader. // Whether the shader is identified as a vertex or pixel shader.
xenos::ShaderType type() const { return shader_type_; } xenos::ShaderType type() const { return shader_type_; }
// If this is a vertex shader, and it has been translated, type of the shader
// in a D3D11-like rendering pipeline - shader interface depends on in, so it
// must be known at translation time.
HostVertexShaderType host_vertex_shader_type() const {
return host_vertex_shader_type_;
}
// Microcode dwords in host endianness. // Microcode dwords in host endianness.
const std::vector<uint32_t>& ucode_data() const { return ucode_data_; } const std::vector<uint32_t>& ucode_data() const { return ucode_data_; }
uint64_t ucode_data_hash() const { return ucode_data_hash_; } uint64_t ucode_data_hash() const { return ucode_data_hash_; }
const uint32_t* ucode_dwords() const { return ucode_data_.data(); } const uint32_t* ucode_dwords() const { return ucode_data_.data(); }
size_t ucode_dword_count() const { return ucode_data_.size(); } size_t ucode_dword_count() const { return ucode_data_.size(); }
// Host translations with the specified modification bits. Not thread-safe
// with respect to translation creation/destruction.
const std::unordered_map<uint32_t, Translation*>& translations() const {
return translations_;
}
Translation* GetTranslation(uint32_t modification) const {
auto it = translations_.find(modification);
if (it != translations_.cend()) {
return it->second;
}
return nullptr;
}
Translation* GetOrCreateTranslation(uint32_t modification,
bool* is_new = nullptr);
// For shader storage loading, to remove a modification in case of translation
// failure. Not thread-safe.
void DestroyTranslation(uint32_t modification);
// All vertex bindings used in the shader. // All vertex bindings used in the shader.
// Valid for vertex shaders only. // Valid for vertex shaders only.
const std::vector<VertexBinding>& vertex_bindings() const { const std::vector<VertexBinding>& vertex_bindings() const {
@ -733,73 +813,55 @@ class Shader {
// True if the shader overrides the pixel depth. // True if the shader overrides the pixel depth.
bool writes_depth() const { return writes_depth_; } bool writes_depth() const { return writes_depth_; }
// True if Xenia can automatically enable early depth/stencil for the pixel // True if the current shader has any `kill` instructions.
// shader when RB_DEPTHCONTROL EARLY_Z_ENABLE is not set, provided alpha bool kills_pixels() const { return kills_pixels_; }
// testing and alpha to coverage are disabled.
bool implicit_early_z_allowed() const { return implicit_early_z_allowed_; }
// True if the shader was translated and prepared without error.
bool is_valid() const { return is_valid_; }
// True if the shader has already been translated.
bool is_translated() const { return is_translated_; }
// Errors that occurred during translation.
const std::vector<Error>& errors() const { return errors_; }
// Microcode disassembly in D3D format. // Microcode disassembly in D3D format.
const std::string& ucode_disassembly() const { return ucode_disassembly_; } const std::string& ucode_disassembly() const { return ucode_disassembly_; }
// Translated shader binary (or text). // An externally managed identifier of the shader storage the microcode of the
const std::vector<uint8_t>& translated_binary() const { // shader was last written to, or was loaded from, to only write the shader
return translated_binary_; // microcode to the storage once. UINT32_MAX by default.
uint32_t ucode_storage_index() const { return ucode_storage_index_; }
void set_ucode_storage_index(uint32_t storage_index) {
ucode_storage_index_ = storage_index;
} }
// Gets the translated shader binary as a string. // Dumps the shader's microcode binary to a file in the given path based on
// This is only valid if it is actually text. // ucode hash. Returns the name of the written file. Can be called at any
std::string GetTranslatedBinaryString() const; // time, doesn't require the shader to be translated.
std::filesystem::path DumpUcodeBinary(const std::filesystem::path& base_path);
// Disassembly of the translated from the host graphics layer.
// May be empty if the host does not support disassembly.
const std::string& host_disassembly() const { return host_disassembly_; }
// A lot of errors that occurred during preparation of the host shader.
const std::string& host_error_log() const { return host_error_log_; }
// Host binary that can be saved and reused across runs.
// May be empty if the host does not support saving binaries.
const std::vector<uint8_t>& host_binary() const { return host_binary_; }
// Dumps the shader to a file in the given path based on ucode hash.
// Both the ucode binary and disassembled and translated shader will be
// written.
// Returns the filename of the shader and the binary.
std::pair<std::filesystem::path, std::filesystem::path> Dump(
const std::filesystem::path& base_path, const char* path_prefix);
protected: protected:
friend class ShaderTranslator; friend class ShaderTranslator;
virtual Translation* CreateTranslationInstance(uint32_t modification);
xenos::ShaderType shader_type_; xenos::ShaderType shader_type_;
HostVertexShaderType host_vertex_shader_type_ = HostVertexShaderType::kVertex;
std::vector<uint32_t> ucode_data_; std::vector<uint32_t> ucode_data_;
uint64_t ucode_data_hash_; uint64_t ucode_data_hash_;
// Modification bits -> translation.
std::unordered_map<uint32_t, Translation*> translations_;
// Whether setup of the post-translation parameters (listed below, plus those
// specific to the implementation) has been initiated, by any thread. If
// translation is performed on multiple threads, only one thread must be
// setting this up (other threads would write the same data anyway).
std::atomic_flag post_translation_info_set_up_ = ATOMIC_FLAG_INIT;
// Initialized after the first successful translation (these don't depend on
// the host-side modification bits).
std::string ucode_disassembly_;
std::vector<VertexBinding> vertex_bindings_; std::vector<VertexBinding> vertex_bindings_;
std::vector<TextureBinding> texture_bindings_; std::vector<TextureBinding> texture_bindings_;
ConstantRegisterMap constant_register_map_ = {0}; ConstantRegisterMap constant_register_map_ = {0};
bool writes_color_targets_[4] = {false, false, false, false}; bool writes_color_targets_[4] = {false, false, false, false};
bool writes_depth_ = false; bool writes_depth_ = false;
bool implicit_early_z_allowed_ = true; bool kills_pixels_ = false;
std::vector<uint32_t> memexport_stream_constants_; std::vector<uint32_t> memexport_stream_constants_;
bool is_valid_ = false; uint32_t ucode_storage_index_ = UINT32_MAX;
bool is_translated_ = false;
std::vector<Error> errors_;
std::string ucode_disassembly_;
std::vector<uint8_t> translated_binary_;
std::string host_disassembly_;
std::string host_error_log_;
std::vector<uint8_t> host_binary_;
}; };
} // namespace gpu } // namespace gpu

View File

@ -140,11 +140,15 @@ int shader_compiler_main(const std::vector<std::string>& args) {
Shader::HostVertexShaderType::kQuadDomainPatchIndexed; Shader::HostVertexShaderType::kQuadDomainPatchIndexed;
} }
} }
uint32_t modification =
translator->GetDefaultModification(shader_type, host_vertex_shader_type);
translator->Translate(shader.get(), host_vertex_shader_type); Shader::Translation* translation =
shader->GetOrCreateTranslation(modification);
translator->Translate(*translation);
const void* source_data = shader->translated_binary().data(); const void* source_data = translation->translated_binary().data();
size_t source_data_size = shader->translated_binary().size(); size_t source_data_size = translation->translated_binary().size();
std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result; std::unique_ptr<xe::ui::spirv::SpirvDisassembler::Result> spirv_disasm_result;
if (cvars::shader_output_type == "spirvtext") { if (cvars::shader_output_type == "spirvtext") {

View File

@ -1,4 +1,3 @@
#include "shader_translator.h"
/** /**
****************************************************************************** ******************************************************************************
* Xenia : Xbox 360 Emulator Research Project * * Xenia : Xbox 360 Emulator Research Project *
@ -14,6 +13,7 @@
#include <set> #include <set>
#include <string> #include <string>
#include "xenia/base/assert.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
#include "xenia/base/math.h" #include "xenia/base/math.h"
@ -46,7 +46,9 @@ ShaderTranslator::ShaderTranslator() = default;
ShaderTranslator::~ShaderTranslator() = default; ShaderTranslator::~ShaderTranslator() = default;
void ShaderTranslator::Reset() { void ShaderTranslator::Reset(xenos::ShaderType shader_type) {
shader_type_ = shader_type;
modification_ = GetDefaultModification(shader_type);
errors_.clear(); errors_.clear();
ucode_disasm_buffer_.Reset(); ucode_disasm_buffer_.Reset();
ucode_disasm_line_number_ = 0; ucode_disasm_line_number_ = 0;
@ -64,37 +66,37 @@ void ShaderTranslator::Reset() {
writes_color_targets_[i] = false; writes_color_targets_[i] = false;
} }
writes_depth_ = false; writes_depth_ = false;
implicit_early_z_allowed_ = true; kills_pixels_ = false;
memexport_alloc_count_ = 0; memexport_alloc_count_ = 0;
memexport_eA_written_ = 0; memexport_eA_written_ = 0;
std::memset(&memexport_eM_written_, 0, sizeof(memexport_eM_written_)); std::memset(&memexport_eM_written_, 0, sizeof(memexport_eM_written_));
memexport_stream_constants_.clear(); memexport_stream_constants_.clear();
} }
bool ShaderTranslator::Translate( bool ShaderTranslator::Translate(Shader::Translation& translation,
Shader* shader, reg::SQ_PROGRAM_CNTL cntl, reg::SQ_PROGRAM_CNTL cntl) {
Shader::HostVertexShaderType host_vertex_shader_type) { xenos::ShaderType shader_type = translation.shader().type();
Reset(); Reset(shader_type);
uint32_t cntl_num_reg = shader->type() == xenos::ShaderType::kVertex uint32_t cntl_num_reg = shader_type == xenos::ShaderType::kVertex
? cntl.vs_num_reg ? cntl.vs_num_reg
: cntl.ps_num_reg; : cntl.ps_num_reg;
register_count_ = (cntl_num_reg & 0x80) ? 0 : (cntl_num_reg + 1); register_count_ = (cntl_num_reg & 0x80) ? 0 : (cntl_num_reg + 1);
return TranslateInternal(shader, host_vertex_shader_type); return TranslateInternal(translation);
} }
bool ShaderTranslator::Translate( bool ShaderTranslator::Translate(Shader::Translation& translation) {
Shader* shader, Shader::HostVertexShaderType host_vertex_shader_type) { Reset(translation.shader().type());
Reset(); return TranslateInternal(translation);
return TranslateInternal(shader, host_vertex_shader_type);
} }
bool ShaderTranslator::TranslateInternal( bool ShaderTranslator::TranslateInternal(Shader::Translation& translation) {
Shader* shader, Shader::HostVertexShaderType host_vertex_shader_type) { Shader& shader = translation.shader();
shader_type_ = shader->type(); assert_true(shader_type_ == shader.type());
host_vertex_shader_type_ = host_vertex_shader_type; shader_type_ = shader.type();
ucode_dwords_ = shader->ucode_dwords(); ucode_dwords_ = shader.ucode_dwords();
ucode_dword_count_ = shader->ucode_dword_count(); ucode_dword_count_ = shader.ucode_dword_count();
modification_ = translation.modification();
// Control flow instructions come paired in blocks of 3 dwords and all are // Control flow instructions come paired in blocks of 3 dwords and all are
// listed at the top of the ucode. // listed at the top of the ucode.
@ -150,12 +152,6 @@ bool ShaderTranslator::TranslateInternal(
if (memexport_eA_written_ == 0) { if (memexport_eA_written_ == 0) {
memexport_stream_constants_.clear(); memexport_stream_constants_.clear();
} }
if (!memexport_stream_constants_.empty()) {
// TODO(Triang3l): Investigate what happens to memexport when the pixel
// fails the depth/stencil test, but in Direct3D 11 UAV writes disable early
// depth/stencil.
implicit_early_z_allowed_ = false;
}
StartTranslation(); StartTranslation();
@ -192,35 +188,44 @@ bool ShaderTranslator::TranslateInternal(
++cf_index; ++cf_index;
} }
shader->errors_ = std::move(errors_); translation.errors_ = std::move(errors_);
shader->translated_binary_ = CompleteTranslation(); translation.translated_binary_ = CompleteTranslation();
shader->ucode_disassembly_ = ucode_disasm_buffer_.to_string(); translation.is_translated_ = true;
shader->host_vertex_shader_type_ = host_vertex_shader_type_;
shader->vertex_bindings_ = std::move(vertex_bindings_);
shader->texture_bindings_ = std::move(texture_bindings_);
shader->constant_register_map_ = std::move(constant_register_map_);
for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) {
shader->writes_color_targets_[i] = writes_color_targets_[i];
}
shader->writes_depth_ = writes_depth_;
shader->implicit_early_z_allowed_ = implicit_early_z_allowed_;
shader->memexport_stream_constants_.clear();
for (uint32_t memexport_stream_constant : memexport_stream_constants_) {
shader->memexport_stream_constants_.push_back(memexport_stream_constant);
}
shader->is_valid_ = true; bool is_valid = true;
shader->is_translated_ = true; for (const auto& error : translation.errors_) {
for (const auto& error : shader->errors_) {
if (error.is_fatal) { if (error.is_fatal) {
shader->is_valid_ = false; is_valid = false;
break; break;
} }
} }
translation.is_valid_ = is_valid;
PostTranslation(shader); // Setup info that doesn't depend on the modification only once.
bool setup_shader_post_translation_info =
is_valid && !shader.post_translation_info_set_up_.test_and_set();
if (setup_shader_post_translation_info) {
shader.ucode_disassembly_ = ucode_disasm_buffer_.to_string();
shader.vertex_bindings_ = std::move(vertex_bindings_);
shader.texture_bindings_ = std::move(texture_bindings_);
shader.constant_register_map_ = std::move(constant_register_map_);
for (size_t i = 0; i < xe::countof(writes_color_targets_); ++i) {
shader.writes_color_targets_[i] = writes_color_targets_[i];
}
shader.writes_depth_ = writes_depth_;
shader.kills_pixels_ = kills_pixels_;
shader.memexport_stream_constants_.clear();
shader.memexport_stream_constants_.reserve(
memexport_stream_constants_.size());
shader.memexport_stream_constants_.insert(
shader.memexport_stream_constants_.cend(),
memexport_stream_constants_.cbegin(),
memexport_stream_constants_.cend());
}
PostTranslation(translation, setup_shader_post_translation_info);
return shader->is_valid_; // In case is_valid_ is modified by PostTranslation, reload.
return translation.is_valid_;
} }
void ShaderTranslator::MarkUcodeInstruction(uint32_t dword_offset) { void ShaderTranslator::MarkUcodeInstruction(uint32_t dword_offset) {
@ -343,14 +348,9 @@ void ShaderTranslator::GatherInstructionInformation(
ParsedAluInstruction instr; ParsedAluInstruction instr;
ParseAluInstruction(op, instr); ParseAluInstruction(op, instr);
const auto& vector_opcode_info = kills_pixels_ = kills_pixels_ ||
alu_vector_opcode_infos_[uint32_t(op.vector_opcode())]; ucode::AluVectorOpcodeIsKill(op.vector_opcode()) ||
implicit_early_z_allowed_ &= ucode::AluScalarOpcodeIsKill(op.scalar_opcode());
!vector_opcode_info.disable_implicit_early_z;
const auto& scalar_opcode_info =
alu_scalar_opcode_infos_[uint32_t(op.scalar_opcode())];
implicit_early_z_allowed_ &=
!scalar_opcode_info.disable_implicit_early_z;
if (instr.vector_and_constant_result.storage_target != if (instr.vector_and_constant_result.storage_target !=
InstructionStorageTarget::kRegister || InstructionStorageTarget::kRegister ||
@ -408,7 +408,6 @@ void ShaderTranslator::GatherInstructionInformation(
break; break;
case InstructionStorageTarget::kDepth: case InstructionStorageTarget::kDepth:
writes_depth_ = true; writes_depth_ = true;
implicit_early_z_allowed_ = false;
break; break;
default: default:
break; break;
@ -1082,91 +1081,91 @@ uint32_t ParsedTextureFetchInstruction::GetNonZeroResultComponents() const {
const ShaderTranslator::AluOpcodeInfo const ShaderTranslator::AluOpcodeInfo
ShaderTranslator::alu_vector_opcode_infos_[0x20] = { ShaderTranslator::alu_vector_opcode_infos_[0x20] = {
{"add", 2, 4, false}, // 0 {"add", 2, 4}, // 0
{"mul", 2, 4, false}, // 1 {"mul", 2, 4}, // 1
{"max", 2, 4, false}, // 2 {"max", 2, 4}, // 2
{"min", 2, 4, false}, // 3 {"min", 2, 4}, // 3
{"seq", 2, 4, false}, // 4 {"seq", 2, 4}, // 4
{"sgt", 2, 4, false}, // 5 {"sgt", 2, 4}, // 5
{"sge", 2, 4, false}, // 6 {"sge", 2, 4}, // 6
{"sne", 2, 4, false}, // 7 {"sne", 2, 4}, // 7
{"frc", 1, 4, false}, // 8 {"frc", 1, 4}, // 8
{"trunc", 1, 4, false}, // 9 {"trunc", 1, 4}, // 9
{"floor", 1, 4, false}, // 10 {"floor", 1, 4}, // 10
{"mad", 3, 4, false}, // 11 {"mad", 3, 4}, // 11
{"cndeq", 3, 4, false}, // 12 {"cndeq", 3, 4}, // 12
{"cndge", 3, 4, false}, // 13 {"cndge", 3, 4}, // 13
{"cndgt", 3, 4, false}, // 14 {"cndgt", 3, 4}, // 14
{"dp4", 2, 4, false}, // 15 {"dp4", 2, 4}, // 15
{"dp3", 2, 4, false}, // 16 {"dp3", 2, 4}, // 16
{"dp2add", 3, 4, false}, // 17 {"dp2add", 3, 4}, // 17
{"cube", 2, 4, false}, // 18 {"cube", 2, 4}, // 18
{"max4", 1, 4, false}, // 19 {"max4", 1, 4}, // 19
{"setp_eq_push", 2, 4, false}, // 20 {"setp_eq_push", 2, 4}, // 20
{"setp_ne_push", 2, 4, false}, // 21 {"setp_ne_push", 2, 4}, // 21
{"setp_gt_push", 2, 4, false}, // 22 {"setp_gt_push", 2, 4}, // 22
{"setp_ge_push", 2, 4, false}, // 23 {"setp_ge_push", 2, 4}, // 23
{"kill_eq", 2, 4, true}, // 24 {"kill_eq", 2, 4}, // 24
{"kill_gt", 2, 4, true}, // 25 {"kill_gt", 2, 4}, // 25
{"kill_ge", 2, 4, true}, // 26 {"kill_ge", 2, 4}, // 26
{"kill_ne", 2, 4, true}, // 27 {"kill_ne", 2, 4}, // 27
{"dst", 2, 4, false}, // 28 {"dst", 2, 4}, // 28
{"maxa", 2, 4, false}, // 29 {"maxa", 2, 4}, // 29
}; };
const ShaderTranslator::AluOpcodeInfo const ShaderTranslator::AluOpcodeInfo
ShaderTranslator::alu_scalar_opcode_infos_[0x40] = { ShaderTranslator::alu_scalar_opcode_infos_[0x40] = {
{"adds", 1, 2, false}, // 0 {"adds", 1, 2}, // 0
{"adds_prev", 1, 1, false}, // 1 {"adds_prev", 1, 1}, // 1
{"muls", 1, 2, false}, // 2 {"muls", 1, 2}, // 2
{"muls_prev", 1, 1, false}, // 3 {"muls_prev", 1, 1}, // 3
{"muls_prev2", 1, 2, false}, // 4 {"muls_prev2", 1, 2}, // 4
{"maxs", 1, 2, false}, // 5 {"maxs", 1, 2}, // 5
{"mins", 1, 2, false}, // 6 {"mins", 1, 2}, // 6
{"seqs", 1, 1, false}, // 7 {"seqs", 1, 1}, // 7
{"sgts", 1, 1, false}, // 8 {"sgts", 1, 1}, // 8
{"sges", 1, 1, false}, // 9 {"sges", 1, 1}, // 9
{"snes", 1, 1, false}, // 10 {"snes", 1, 1}, // 10
{"frcs", 1, 1, false}, // 11 {"frcs", 1, 1}, // 11
{"truncs", 1, 1, false}, // 12 {"truncs", 1, 1}, // 12
{"floors", 1, 1, false}, // 13 {"floors", 1, 1}, // 13
{"exp", 1, 1, false}, // 14 {"exp", 1, 1}, // 14
{"logc", 1, 1, false}, // 15 {"logc", 1, 1}, // 15
{"log", 1, 1, false}, // 16 {"log", 1, 1}, // 16
{"rcpc", 1, 1, false}, // 17 {"rcpc", 1, 1}, // 17
{"rcpf", 1, 1, false}, // 18 {"rcpf", 1, 1}, // 18
{"rcp", 1, 1, false}, // 19 {"rcp", 1, 1}, // 19
{"rsqc", 1, 1, false}, // 20 {"rsqc", 1, 1}, // 20
{"rsqf", 1, 1, false}, // 21 {"rsqf", 1, 1}, // 21
{"rsq", 1, 1, false}, // 22 {"rsq", 1, 1}, // 22
{"maxas", 1, 2, false}, // 23 {"maxas", 1, 2}, // 23
{"maxasf", 1, 2, false}, // 24 {"maxasf", 1, 2}, // 24
{"subs", 1, 2, false}, // 25 {"subs", 1, 2}, // 25
{"subs_prev", 1, 1, false}, // 26 {"subs_prev", 1, 1}, // 26
{"setp_eq", 1, 1, false}, // 27 {"setp_eq", 1, 1}, // 27
{"setp_ne", 1, 1, false}, // 28 {"setp_ne", 1, 1}, // 28
{"setp_gt", 1, 1, false}, // 29 {"setp_gt", 1, 1}, // 29
{"setp_ge", 1, 1, false}, // 30 {"setp_ge", 1, 1}, // 30
{"setp_inv", 1, 1, false}, // 31 {"setp_inv", 1, 1}, // 31
{"setp_pop", 1, 1, false}, // 32 {"setp_pop", 1, 1}, // 32
{"setp_clr", 0, 0, false}, // 33 {"setp_clr", 0, 0}, // 33
{"setp_rstr", 1, 1, false}, // 34 {"setp_rstr", 1, 1}, // 34
{"kills_eq", 1, 1, true}, // 35 {"kills_eq", 1, 1}, // 35
{"kills_gt", 1, 1, true}, // 36 {"kills_gt", 1, 1}, // 36
{"kills_ge", 1, 1, true}, // 37 {"kills_ge", 1, 1}, // 37
{"kills_ne", 1, 1, true}, // 38 {"kills_ne", 1, 1}, // 38
{"kills_one", 1, 1, true}, // 39 {"kills_one", 1, 1}, // 39
{"sqrt", 1, 1, false}, // 40 {"sqrt", 1, 1}, // 40
{"UNKNOWN", 0, 0, false}, // 41 {"UNKNOWN", 0, 0}, // 41
{"mulsc", 2, 1, false}, // 42 {"mulsc", 2, 1}, // 42
{"mulsc", 2, 1, false}, // 43 {"mulsc", 2, 1}, // 43
{"addsc", 2, 1, false}, // 44 {"addsc", 2, 1}, // 44
{"addsc", 2, 1, false}, // 45 {"addsc", 2, 1}, // 45
{"subsc", 2, 1, false}, // 46 {"subsc", 2, 1}, // 46
{"subsc", 2, 1, false}, // 47 {"subsc", 2, 1}, // 47
{"sin", 1, 1, false}, // 48 {"sin", 1, 1}, // 48
{"cos", 1, 1, false}, // 49 {"cos", 1, 1}, // 49
{"retain_prev", 0, 0, false}, // 50 {"retain_prev", 0, 0}, // 50
}; };
void ShaderTranslator::TranslateAluInstruction(const AluInstruction& op) { void ShaderTranslator::TranslateAluInstruction(const AluInstruction& op) {

View File

@ -29,18 +29,27 @@ class ShaderTranslator {
public: public:
virtual ~ShaderTranslator(); virtual ~ShaderTranslator();
bool Translate(Shader* shader, reg::SQ_PROGRAM_CNTL cntl, virtual uint32_t GetDefaultModification(
Shader::HostVertexShaderType host_vertex_shader_type = xenos::ShaderType shader_type,
Shader::HostVertexShaderType::kVertex); Shader::HostVertexShaderType host_vertex_shader_type =
bool Translate(Shader* shader, Shader::HostVertexShaderType::kVertex) const {
Shader::HostVertexShaderType host_vertex_shader_type = return 0;
Shader::HostVertexShaderType::kVertex); }
bool Translate(Shader::Translation& translation, reg::SQ_PROGRAM_CNTL cntl);
bool Translate(Shader::Translation& translation);
protected: protected:
ShaderTranslator(); ShaderTranslator();
// Resets translator state before beginning translation. // Resets translator state before beginning translation.
virtual void Reset(); // shader_type is passed here so translator implementations can generate
// special fixed shaders for internal use, and set up the type for this
// purpose.
virtual void Reset(xenos::ShaderType shader_type);
// Current host-side modification being generated.
uint32_t modification() const { return modification_; }
// Register count. // Register count.
uint32_t register_count() const { return register_count_; } uint32_t register_count() const { return register_count_; }
@ -48,11 +57,6 @@ class ShaderTranslator {
bool is_vertex_shader() const { bool is_vertex_shader() const {
return shader_type_ == xenos::ShaderType::kVertex; return shader_type_ == xenos::ShaderType::kVertex;
} }
// If translating a vertex shader, type of the shader in a D3D11-like
// rendering pipeline.
Shader::HostVertexShaderType host_vertex_shader_type() const {
return host_vertex_shader_type_;
}
// True if the current shader is a pixel shader. // True if the current shader is a pixel shader.
bool is_pixel_shader() const { bool is_pixel_shader() const {
return shader_type_ == xenos::ShaderType::kPixel; return shader_type_ == xenos::ShaderType::kPixel;
@ -85,10 +89,8 @@ class ShaderTranslator {
// True if the current shader overrides the pixel depth, set before // True if the current shader overrides the pixel depth, set before
// translation. Doesn't include writes with an empty used write mask. // translation. Doesn't include writes with an empty used write mask.
bool writes_depth() const { return writes_depth_; } bool writes_depth() const { return writes_depth_; }
// True if Xenia can automatically enable early depth/stencil for the pixel // True if the current shader has any `kill` instructions.
// shader when RB_DEPTHCONTROL EARLY_Z_ENABLE is not set, provided alpha bool kills_pixels() const { return kills_pixels_; }
// testing and alpha to coverage are disabled.
bool implicit_early_z_allowed() const { return implicit_early_z_allowed_; }
// A list of all vertex bindings, populated before translation occurs. // A list of all vertex bindings, populated before translation occurs.
const std::vector<Shader::VertexBinding>& vertex_bindings() const { const std::vector<Shader::VertexBinding>& vertex_bindings() const {
return vertex_bindings_; return vertex_bindings_;
@ -112,6 +114,17 @@ class ShaderTranslator {
return memexport_stream_constants_; return memexport_stream_constants_;
} }
// Whether the shader can have early depth and stencil writing enabled, unless
// alpha test or alpha to coverage is enabled. Data gathered before
// translation.
bool CanWriteZEarly() const {
// TODO(Triang3l): Investigate what happens to memexport when the pixel
// fails the depth/stencil test, but in Direct3D 11 UAV writes disable early
// depth/stencil.
return !writes_depth_ && !kills_pixels_ &&
memexport_stream_constants_.empty();
}
// Current line number in the ucode disassembly. // Current line number in the ucode disassembly.
size_t ucode_disasm_line_number() const { return ucode_disasm_line_number_; } size_t ucode_disasm_line_number() const { return ucode_disasm_line_number_; }
// Ucode disassembly buffer accumulated during translation. // Ucode disassembly buffer accumulated during translation.
@ -130,10 +143,14 @@ class ShaderTranslator {
} }
// Handles post-translation tasks when the shader has been fully translated. // Handles post-translation tasks when the shader has been fully translated.
virtual void PostTranslation(Shader* shader) {} // setup_shader_post_translation_info if non-modification-specific parameters
// of the Shader object behind the Translation can be set by this invocation.
virtual void PostTranslation(Shader::Translation& translation,
bool setup_shader_post_translation_info) {}
// Sets the host disassembly on a shader. // Sets the host disassembly on a shader.
void set_host_disassembly(Shader* shader, std::string value) { void set_host_disassembly(Shader::Translation& translation,
shader->host_disassembly_ = std::move(value); std::string value) {
translation.host_disassembly_ = std::move(value);
} }
// Pre-process a control-flow instruction before anything else. // Pre-process a control-flow instruction before anything else.
@ -188,11 +205,9 @@ class ShaderTranslator {
const char* name; const char* name;
uint32_t argument_count; uint32_t argument_count;
uint32_t src_swizzle_component_count; uint32_t src_swizzle_component_count;
bool disable_implicit_early_z;
}; };
bool TranslateInternal(Shader* shader, bool TranslateInternal(Shader::Translation& translation);
Shader::HostVertexShaderType host_vertex_shader_type);
void MarkUcodeInstruction(uint32_t dword_offset); void MarkUcodeInstruction(uint32_t dword_offset);
void AppendUcodeDisasm(char c); void AppendUcodeDisasm(char c);
@ -246,12 +261,13 @@ class ShaderTranslator {
// Input shader metadata and microcode. // Input shader metadata and microcode.
xenos::ShaderType shader_type_; xenos::ShaderType shader_type_;
Shader::HostVertexShaderType host_vertex_shader_type_;
const uint32_t* ucode_dwords_; const uint32_t* ucode_dwords_;
size_t ucode_dword_count_; size_t ucode_dword_count_;
reg::SQ_PROGRAM_CNTL program_cntl_;
uint32_t register_count_; uint32_t register_count_;
// Current host-side modification being generated.
uint32_t modification_ = 0;
// Accumulated translation errors. // Accumulated translation errors.
std::vector<Shader::Error> errors_; std::vector<Shader::Error> errors_;
@ -272,7 +288,8 @@ class ShaderTranslator {
// translation. // translation.
std::set<uint32_t> label_addresses_; std::set<uint32_t> label_addresses_;
// Detected binding information gathered before translation. // Detected binding information gathered before translation. Must not be
// affected by the modification index.
int total_attrib_count_ = 0; int total_attrib_count_ = 0;
std::vector<Shader::VertexBinding> vertex_bindings_; std::vector<Shader::VertexBinding> vertex_bindings_;
std::vector<Shader::TextureBinding> texture_bindings_; std::vector<Shader::TextureBinding> texture_bindings_;
@ -282,13 +299,15 @@ class ShaderTranslator {
// These all are gathered before translation. // These all are gathered before translation.
// uses_register_dynamic_addressing_ for writes, writes_color_targets_, // uses_register_dynamic_addressing_ for writes, writes_color_targets_,
// writes_depth_ don't include empty used write masks. // writes_depth_ don't include empty used write masks.
// Must not be affected by the modification index.
Shader::ConstantRegisterMap constant_register_map_ = {0}; Shader::ConstantRegisterMap constant_register_map_ = {0};
bool uses_register_dynamic_addressing_ = false; bool uses_register_dynamic_addressing_ = false;
bool writes_color_targets_[4] = {false, false, false, false}; bool writes_color_targets_[4] = {false, false, false, false};
bool writes_depth_ = false; bool writes_depth_ = false;
bool implicit_early_z_allowed_ = true; bool kills_pixels_ = false;
// Memexport info is gathered before translation. // Memexport info is gathered before translation.
// Must not be affected by the modification index.
uint32_t memexport_alloc_count_ = 0; uint32_t memexport_alloc_count_ = 0;
// For register allocation in implementations - what was used after each // For register allocation in implementations - what was used after each
// `alloc export`. // `alloc export`.

View File

@ -667,12 +667,14 @@ std::vector<uint8_t> SpirvShaderTranslator::CompleteTranslation() {
return spirv_bytes; return spirv_bytes;
} }
void SpirvShaderTranslator::PostTranslation(Shader* shader) { void SpirvShaderTranslator::PostTranslation(
Shader::Translation& translation, bool setup_shader_post_translation_info) {
// Validation. // Validation.
if (cvars::spv_validate) { if (cvars::spv_validate) {
auto validation = validator_.Validate( auto validation = validator_.Validate(
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()), reinterpret_cast<const uint32_t*>(
shader->translated_binary().size() / sizeof(uint32_t)); translation.translated_binary().data()),
translation.translated_binary().size() / sizeof(uint32_t));
if (validation->has_error()) { if (validation->has_error()) {
XELOGE("SPIR-V Shader Validation failed! Error: {}", XELOGE("SPIR-V Shader Validation failed! Error: {}",
validation->error_string()); validation->error_string());
@ -682,12 +684,13 @@ void SpirvShaderTranslator::PostTranslation(Shader* shader) {
if (cvars::spv_disasm) { if (cvars::spv_disasm) {
// TODO(benvanik): only if needed? could be slowish. // TODO(benvanik): only if needed? could be slowish.
auto disasm = disassembler_.Disassemble( auto disasm = disassembler_.Disassemble(
reinterpret_cast<const uint32_t*>(shader->translated_binary().data()), reinterpret_cast<const uint32_t*>(
shader->translated_binary().size() / 4); translation.translated_binary().data()),
translation.translated_binary().size() / sizeof(uint32_t));
if (disasm->has_error()) { if (disasm->has_error()) {
XELOGE("Failed to disassemble SPIRV - invalid?"); XELOGE("Failed to disassemble SPIRV - invalid?");
} else { } else {
set_host_disassembly(shader, disasm->to_string()); set_host_disassembly(translation, disasm->to_string());
} }
} }
} }

View File

@ -61,7 +61,8 @@ class SpirvShaderTranslator : public ShaderTranslator {
protected: protected:
void StartTranslation() override; void StartTranslation() override;
std::vector<uint8_t> CompleteTranslation() override; std::vector<uint8_t> CompleteTranslation() override;
void PostTranslation(Shader* shader) override; void PostTranslation(Shader::Translation& translation,
bool setup_shader_post_translation_info) override;
void PreProcessControlFlowInstructions( void PreProcessControlFlowInstructions(
std::vector<ucode::ControlFlowInstruction> instrs) override; std::vector<ucode::ControlFlowInstruction> instrs) override;

View File

@ -92,7 +92,7 @@ int TraceDump::Main(const std::vector<std::string>& args) {
bool TraceDump::Setup() { bool TraceDump::Setup() {
// Create the emulator but don't initialize so we can setup the window. // Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>("", "", ""); emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup( X_STATUS result = emulator_->Setup(
nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr); nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr);
if (XFAILED(result)) { if (XFAILED(result)) {

View File

@ -121,7 +121,7 @@ bool TraceViewer::Setup() {
window_->Resize(1920, 1200); window_->Resize(1920, 1200);
// Create the emulator but don't initialize so we can setup the window. // Create the emulator but don't initialize so we can setup the window.
emulator_ = std::make_unique<Emulator>("", "", ""); emulator_ = std::make_unique<Emulator>("", "", "", "");
X_STATUS result = emulator_->Setup( X_STATUS result = emulator_->Setup(
window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); }, window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); },
nullptr); nullptr);
@ -566,8 +566,21 @@ TraceViewer::ShaderDisplayType TraceViewer::DrawShaderTypeUI() {
void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) { void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) {
// Must be prepared for advanced display modes. // Must be prepared for advanced display modes.
// FIXME(Triang3l): This should display the actual translation used in the
// draw, but it may depend on multiple backend-related factors, including
// drawing multiple times with multiple modifications, even depending on
// values obtained during translation of other modifications (for instance,
// a memexporting shader can be executed both as a vertex shader (to draw the
// points) and as a compute shader (to actually export) if the host doesn't
// support writes from vertex shaders.
const Shader::Translation* translation = nullptr;
if (display_type != ShaderDisplayType::kUcode) { if (display_type != ShaderDisplayType::kUcode) {
if (!shader->is_valid()) { for (const auto& translation_pair : shader->translations()) {
if (translation_pair.second->is_valid()) {
translation = translation_pair.second;
}
}
if (!translation) {
ImGui::TextColored(kColorError, ImGui::TextColored(kColorError,
"ERROR: shader error during parsing/translation"); "ERROR: shader error during parsing/translation");
return; return;
@ -580,7 +593,7 @@ void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) {
break; break;
} }
case ShaderDisplayType::kTranslated: { case ShaderDisplayType::kTranslated: {
const auto& str = shader->GetTranslatedBinaryString(); const auto& str = translation->GetTranslatedBinaryString();
size_t i = 0; size_t i = 0;
bool done = false; bool done = false;
while (!done && i < str.size()) { while (!done && i < str.size()) {
@ -600,7 +613,7 @@ void TraceViewer::DrawShaderUI(Shader* shader, ShaderDisplayType display_type) {
break; break;
} }
case ShaderDisplayType::kHostDisasm: { case ShaderDisplayType::kHostDisasm: {
DrawMultilineString(shader->host_disassembly()); DrawMultilineString(translation->host_disassembly());
break; break;
} }
} }

View File

@ -1147,6 +1147,19 @@ enum class AluScalarOpcode : uint32_t {
kRetainPrev = 50, kRetainPrev = 50,
}; };
constexpr bool AluScalarOpcodeIsKill(AluScalarOpcode scalar_opcode) {
switch (scalar_opcode) {
case AluScalarOpcode::kKillsEq:
case AluScalarOpcode::kKillsGt:
case AluScalarOpcode::kKillsGe:
case AluScalarOpcode::kKillsNe:
case AluScalarOpcode::kKillsOne:
return true;
default:
return false;
}
}
enum class AluVectorOpcode : uint32_t { enum class AluVectorOpcode : uint32_t {
// Per-Component Floating-Point Add // Per-Component Floating-Point Add
// add/ADDv dest, src0, src1 // add/ADDv dest, src0, src1
@ -1471,27 +1484,37 @@ enum class AluVectorOpcode : uint32_t {
kMaxA = 29, kMaxA = 29,
}; };
constexpr bool AluVectorOpcodeIsKill(AluVectorOpcode vector_opcode) {
switch (vector_opcode) {
case AluVectorOpcode::kKillEq:
case AluVectorOpcode::kKillGt:
case AluVectorOpcode::kKillGe:
case AluVectorOpcode::kKillNe:
return true;
default:
return false;
}
}
// Whether the vector instruction has side effects such as discarding a pixel or // Whether the vector instruction has side effects such as discarding a pixel or
// setting the predicate and can't be ignored even if it doesn't write to // setting the predicate and can't be ignored even if it doesn't write to
// anywhere. Note that all scalar operations except for retain_prev have a side // anywhere. Note that all scalar operations except for retain_prev have a side
// effect of modifying the previous scalar result register, so they must always // effect of modifying the previous scalar result register, so they must always
// be executed even if not writing. // be executed even if not writing.
constexpr bool AluVectorOpHasSideEffects(AluVectorOpcode vector_opcode) { constexpr bool AluVectorOpHasSideEffects(AluVectorOpcode vector_opcode) {
if (AluVectorOpcodeIsKill(vector_opcode)) {
return true;
}
switch (vector_opcode) { switch (vector_opcode) {
case AluVectorOpcode::kSetpEqPush: case AluVectorOpcode::kSetpEqPush:
case AluVectorOpcode::kSetpNePush: case AluVectorOpcode::kSetpNePush:
case AluVectorOpcode::kSetpGtPush: case AluVectorOpcode::kSetpGtPush:
case AluVectorOpcode::kSetpGePush: case AluVectorOpcode::kSetpGePush:
case AluVectorOpcode::kKillEq:
case AluVectorOpcode::kKillGt:
case AluVectorOpcode::kKillGe:
case AluVectorOpcode::kKillNe:
case AluVectorOpcode::kMaxA: case AluVectorOpcode::kMaxA:
return true; return true;
default: default:
break; return false;
} }
return false;
} }
// Whether each component of a source operand is used at all in the instruction // Whether each component of a source operand is used at all in the instruction

View File

@ -362,35 +362,38 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state,
return pipeline; return pipeline;
} }
bool PipelineCache::TranslateShader(VulkanShader* shader, bool PipelineCache::TranslateShader(
reg::SQ_PROGRAM_CNTL cntl) { VulkanShader::VulkanTranslation& translation, reg::SQ_PROGRAM_CNTL cntl) {
// Perform translation. // Perform translation.
// If this fails the shader will be marked as invalid and ignored later. // If this fails the shader will be marked as invalid and ignored later.
if (!shader_translator_->Translate(shader, cntl)) { if (!shader_translator_->Translate(translation, cntl)) {
XELOGE("Shader translation failed; marking shader as ignored"); XELOGE("Shader translation failed; marking shader as ignored");
return false; return false;
} }
// Prepare the shader for use (creates our VkShaderModule). // Prepare the shader for use (creates our VkShaderModule).
// It could still fail at this point. // It could still fail at this point.
if (!shader->Prepare()) { if (!translation.Prepare()) {
XELOGE("Shader preparation failed; marking shader as ignored"); XELOGE("Shader preparation failed; marking shader as ignored");
return false; return false;
} }
if (shader->is_valid()) { if (translation.is_valid()) {
XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n", XELOGGPU("Generated {} shader ({}b) - hash {:016X}:\n{}\n",
shader->type() == xenos::ShaderType::kVertex ? "vertex" : "pixel", translation.shader().type() == xenos::ShaderType::kVertex
shader->ucode_dword_count() * 4, shader->ucode_data_hash(), ? "vertex"
shader->ucode_disassembly()); : "pixel",
translation.shader().ucode_dword_count() * 4,
translation.shader().ucode_data_hash(),
translation.shader().ucode_disassembly());
} }
// Dump shader files if desired. // Dump shader files if desired.
if (!cvars::dump_shaders.empty()) { if (!cvars::dump_shaders.empty()) {
shader->Dump(cvars::dump_shaders, "vk"); translation.Dump(cvars::dump_shaders, "vk");
} }
return shader->is_valid(); return translation.is_valid();
} }
static void DumpShaderStatisticsAMD(const VkShaderStatisticsInfoAMD& stats) { static void DumpShaderStatisticsAMD(const VkShaderStatisticsInfoAMD& stats) {
@ -1063,16 +1066,28 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
return UpdateStatus::kCompatible; return UpdateStatus::kCompatible;
} }
if (!vertex_shader->is_translated() && VulkanShader::VulkanTranslation* vertex_shader_translation =
!TranslateShader(vertex_shader, regs.sq_program_cntl)) { static_cast<VulkanShader::VulkanTranslation*>(
vertex_shader->GetOrCreateTranslation(
shader_translator_->GetDefaultModification(
xenos::ShaderType::kVertex)));
if (!vertex_shader_translation->is_translated() &&
!TranslateShader(*vertex_shader_translation, regs.sq_program_cntl)) {
XELOGE("Failed to translate the vertex shader!"); XELOGE("Failed to translate the vertex shader!");
return UpdateStatus::kError; return UpdateStatus::kError;
} }
if (pixel_shader && !pixel_shader->is_translated() && VulkanShader::VulkanTranslation* pixel_shader_translation = nullptr;
!TranslateShader(pixel_shader, regs.sq_program_cntl)) { if (pixel_shader) {
XELOGE("Failed to translate the pixel shader!"); pixel_shader_translation = static_cast<VulkanShader::VulkanTranslation*>(
return UpdateStatus::kError; pixel_shader->GetOrCreateTranslation(
shader_translator_->GetDefaultModification(
xenos::ShaderType::kPixel)));
if (!pixel_shader_translation->is_translated() &&
!TranslateShader(*pixel_shader_translation, regs.sq_program_cntl)) {
XELOGE("Failed to translate the pixel shader!");
return UpdateStatus::kError;
}
} }
update_shader_stages_stage_count_ = 0; update_shader_stages_stage_count_ = 0;
@ -1084,7 +1099,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
vertex_pipeline_stage.pNext = nullptr; vertex_pipeline_stage.pNext = nullptr;
vertex_pipeline_stage.flags = 0; vertex_pipeline_stage.flags = 0;
vertex_pipeline_stage.stage = VK_SHADER_STAGE_VERTEX_BIT; vertex_pipeline_stage.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertex_pipeline_stage.module = vertex_shader->shader_module(); vertex_pipeline_stage.module = vertex_shader_translation->shader_module();
vertex_pipeline_stage.pName = "main"; vertex_pipeline_stage.pName = "main";
vertex_pipeline_stage.pSpecializationInfo = nullptr; vertex_pipeline_stage.pSpecializationInfo = nullptr;
@ -1116,8 +1131,9 @@ PipelineCache::UpdateStatus PipelineCache::UpdateShaderStages(
pixel_pipeline_stage.pNext = nullptr; pixel_pipeline_stage.pNext = nullptr;
pixel_pipeline_stage.flags = 0; pixel_pipeline_stage.flags = 0;
pixel_pipeline_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; pixel_pipeline_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
pixel_pipeline_stage.module = pixel_pipeline_stage.module = pixel_shader_translation
pixel_shader ? pixel_shader->shader_module() : dummy_pixel_shader_; ? pixel_shader_translation->shader_module()
: dummy_pixel_shader_;
pixel_pipeline_stage.pName = "main"; pixel_pipeline_stage.pName = "main";
pixel_pipeline_stage.pSpecializationInfo = nullptr; pixel_pipeline_stage.pSpecializationInfo = nullptr;

View File

@ -79,7 +79,8 @@ class PipelineCache {
// state. // state.
VkPipeline GetPipeline(const RenderState* render_state, uint64_t hash_key); VkPipeline GetPipeline(const RenderState* render_state, uint64_t hash_key);
bool TranslateShader(VulkanShader* shader, reg::SQ_PROGRAM_CNTL cntl); bool TranslateShader(VulkanShader::VulkanTranslation& translation,
reg::SQ_PROGRAM_CNTL cntl);
void DumpShaderDisasmAMD(VkPipeline pipeline); void DumpShaderDisasmAMD(VkPipeline pipeline);
void DumpShaderDisasmNV(const VkGraphicsPipelineCreateInfo& info); void DumpShaderDisasmNV(const VkGraphicsPipelineCreateInfo& info);

View File

@ -27,38 +27,56 @@ VulkanShader::VulkanShader(ui::vulkan::VulkanDevice* device,
const uint32_t* dword_ptr, uint32_t dword_count) const uint32_t* dword_ptr, uint32_t dword_count)
: Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {} : Shader(shader_type, data_hash, dword_ptr, dword_count), device_(device) {}
VulkanShader::~VulkanShader() { VulkanShader::VulkanTranslation::~VulkanTranslation() {
if (shader_module_) { if (shader_module_) {
vkDestroyShaderModule(*device_, shader_module_, nullptr); const VulkanShader& vulkan_shader = static_cast<VulkanShader&>(shader());
vkDestroyShaderModule(*vulkan_shader.device_, shader_module_, nullptr);
shader_module_ = nullptr; shader_module_ = nullptr;
} }
} }
bool VulkanShader::Prepare() { bool VulkanShader::VulkanTranslation::Prepare() {
assert_null(shader_module_); assert_null(shader_module_);
assert_true(is_valid()); assert_true(is_valid());
const VulkanShader& vulkan_shader = static_cast<VulkanShader&>(shader());
ui::vulkan::VulkanDevice* device = vulkan_shader.device_;
// Create the shader module. // Create the shader module.
VkShaderModuleCreateInfo shader_info; VkShaderModuleCreateInfo shader_info;
shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_info.pNext = nullptr; shader_info.pNext = nullptr;
shader_info.flags = 0; shader_info.flags = 0;
shader_info.codeSize = translated_binary_.size(); shader_info.codeSize = translated_binary().size();
shader_info.pCode = shader_info.pCode =
reinterpret_cast<const uint32_t*>(translated_binary_.data()); reinterpret_cast<const uint32_t*>(translated_binary().data());
auto status = auto status =
vkCreateShaderModule(*device_, &shader_info, nullptr, &shader_module_); vkCreateShaderModule(*device, &shader_info, nullptr, &shader_module_);
CheckResult(status, "vkCreateShaderModule"); CheckResult(status, "vkCreateShaderModule");
char typeChar = shader_type_ == xenos::ShaderType::kPixel char type_char;
? 'p' switch (vulkan_shader.type()) {
: shader_type_ == xenos::ShaderType::kVertex ? 'v' : 'u'; case xenos::ShaderType::kVertex:
device_->DbgSetObjectName( type_char = 'v';
uint64_t(shader_module_), VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, break;
fmt::format("S({}): {:016X}", typeChar, ucode_data_hash())); case xenos::ShaderType::kPixel:
type_char = 'p';
break;
default:
type_char = 'u';
}
device->DbgSetObjectName(uint64_t(shader_module_),
VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT,
fmt::format("S({}): {:016X}", type_char,
vulkan_shader.ucode_data_hash()));
return status == VK_SUCCESS; return status == VK_SUCCESS;
} }
Shader::Translation* VulkanShader::CreateTranslationInstance(
uint32_t modification) {
return new VulkanTranslation(*this, modification);
}
} // namespace vulkan } // namespace vulkan
} // namespace gpu } // namespace gpu
} // namespace xe } // namespace xe

View File

@ -21,19 +21,30 @@ namespace vulkan {
class VulkanShader : public Shader { class VulkanShader : public Shader {
public: public:
class VulkanTranslation : public Translation {
public:
VulkanTranslation(VulkanShader& shader, uint32_t modification)
: Translation(shader, modification) {}
~VulkanTranslation() override;
bool Prepare();
// Available only if the translation is_valid and has been prepared.
VkShaderModule shader_module() const { return shader_module_; }
private:
VkShaderModule shader_module_ = nullptr;
};
VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type, VulkanShader(ui::vulkan::VulkanDevice* device, xenos::ShaderType shader_type,
uint64_t data_hash, const uint32_t* dword_ptr, uint64_t data_hash, const uint32_t* dword_ptr,
uint32_t dword_count); uint32_t dword_count);
~VulkanShader() override;
// Available only if the shader is_valid and has been prepared. protected:
VkShaderModule shader_module() const { return shader_module_; } Translation* CreateTranslationInstance(uint32_t modification) override;
bool Prepare();
private: private:
ui::vulkan::VulkanDevice* device_ = nullptr; ui::vulkan::VulkanDevice* device_ = nullptr;
VkShaderModule shader_module_ = nullptr;
}; };
} // namespace vulkan } // namespace vulkan

View File

@ -9,17 +9,41 @@
#include "xenia/gpu/xenos.h" #include "xenia/gpu/xenos.h"
#include <cmath>
#include "xenia/base/math.h" #include "xenia/base/math.h"
namespace xe { namespace xe {
namespace gpu { namespace gpu {
namespace xenos { namespace xenos {
// Based on CFloat24 from d3dref9.dll and the 6e4 code from:
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// 6e4 has a different exponent bias allowing [0,512) values, 20e4 allows [0,2).
uint32_t Float32To20e4(float f32) {
if (!(f32 > 0.0f)) {
// Positive only, and not -0 or NaN.
return 0;
}
uint32_t f32u32 = *reinterpret_cast<const uint32_t*>(&f32);
if (f32u32 >= 0x3FFFFFF8) {
// Saturate.
return 0xFFFFFF;
}
if (f32u32 < 0x38800000) {
// The number is too small to be represented as a normalized 20e4.
// Convert it to a denormalized value.
uint32_t shift = std::min(uint32_t(113 - (f32u32 >> 23)), uint32_t(24));
f32u32 = (0x800000 | (f32u32 & 0x7FFFFF)) >> shift;
} else {
// Rebias the exponent to represent the value as a normalized 20e4.
f32u32 += 0xC8000000u;
}
return ((f32u32 + 3 + ((f32u32 >> 3) & 1)) >> 3) & 0xFFFFFF;
}
float Float20e4To32(uint32_t f24) { float Float20e4To32(uint32_t f24) {
// Based on CFloat24 from d3dref9.dll and the 6e4 code from:
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// 6e4 has a different exponent bias allowing [0,512) values, 20e4 allows
// [0,2).
f24 &= 0xFFFFFF; f24 &= 0xFFFFFF;
if (!f24) { if (!f24) {
return 0.0f; return 0.0f;

View File

@ -305,6 +305,9 @@ enum class DepthRenderTargetFormat : uint32_t {
const char* GetDepthRenderTargetFormatName(DepthRenderTargetFormat format); const char* GetDepthRenderTargetFormatName(DepthRenderTargetFormat format);
// Converts an IEEE-754 32-bit floating-point number to Xenos floating-point
// depth, rounding to the nearest even.
uint32_t Float32To20e4(float f32);
// Converts Xenos floating-point depth in bits 0:23 (not clamping) to an // Converts Xenos floating-point depth in bits 0:23 (not clamping) to an
// IEEE-754 32-bit floating-point number. // IEEE-754 32-bit floating-point number.
float Float20e4To32(uint32_t f24); float Float20e4To32(uint32_t f24);